Orderbook Simulation
OrderbookSim is a C++ application simulating a financial market order book. It efficiently manages and matches buy and sell orders while calculating the Volume-Weighted Average Price (VWAP).
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.11.3
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26#include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.11.3
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.11.3
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
63#warning "Already included a different version of the library!"
64#endif
65#endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73#define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
77#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
78#endif
79
80#if JSON_DIAGNOSTICS
81#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
82#else
83#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
84#endif
85
86#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
87#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
88#else
89#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
90#endif
91
92#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
93#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
94#endif
95
96// Construct the namespace ABI tags component
97#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
98#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
99 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
100
101#define NLOHMANN_JSON_ABI_TAGS \
102 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
103 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
104 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
105
106// Construct the namespace version component
107#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
108 _v ## major ## _ ## minor ## _ ## patch
109#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
110 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
111
112#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
113#define NLOHMANN_JSON_NAMESPACE_VERSION
114#else
115#define NLOHMANN_JSON_NAMESPACE_VERSION \
116 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
117 NLOHMANN_JSON_VERSION_MINOR, \
118 NLOHMANN_JSON_VERSION_PATCH)
119#endif
120
121// Combine namespace components
122#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
123#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
124 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
125
126#ifndef NLOHMANN_JSON_NAMESPACE
127#define NLOHMANN_JSON_NAMESPACE \
128 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
129 NLOHMANN_JSON_ABI_TAGS, \
130 NLOHMANN_JSON_NAMESPACE_VERSION)
131#endif
132
133#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
134#define NLOHMANN_JSON_NAMESPACE_BEGIN \
135 namespace nlohmann \
136 { \
137 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
138 NLOHMANN_JSON_ABI_TAGS, \
139 NLOHMANN_JSON_NAMESPACE_VERSION) \
140 {
141#endif
142
143#ifndef NLOHMANN_JSON_NAMESPACE_END
144#define NLOHMANN_JSON_NAMESPACE_END \
145 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
146 } // namespace nlohmann
147#endif
148
149// #include <nlohmann/detail/conversions/from_json.hpp>
150// __ _____ _____ _____
151// __| | __| | | | JSON for Modern C++
152// | | |__ | | | | | | version 3.11.3
153// |_____|_____|_____|_|___| https://github.com/nlohmann/json
154//
155// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
156// SPDX-License-Identifier: MIT
157
158
159
160#include <algorithm> // transform
161#include <array> // array
162#include <forward_list> // forward_list
163#include <iterator> // inserter, front_inserter, end
164#include <map> // map
165#include <string> // string
166#include <tuple> // tuple, make_tuple
167#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
168#include <unordered_map> // unordered_map
169#include <utility> // pair, declval
170#include <valarray> // valarray
171
172// #include <nlohmann/detail/exceptions.hpp>
173// __ _____ _____ _____
174// __| | __| | | | JSON for Modern C++
175// | | |__ | | | | | | version 3.11.3
176// |_____|_____|_____|_|___| https://github.com/nlohmann/json
177//
178// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
179// SPDX-License-Identifier: MIT
180
181
182
183#include <cstddef> // nullptr_t
184#include <exception> // exception
185#if JSON_DIAGNOSTICS
186#include <numeric> // accumulate
187#endif
188#include <stdexcept> // runtime_error
189#include <string> // to_string
190#include <vector> // vector
191
192// #include <nlohmann/detail/value_t.hpp>
193// __ _____ _____ _____
194// __| | __| | | | JSON for Modern C++
195// | | |__ | | | | | | version 3.11.3
196// |_____|_____|_____|_|___| https://github.com/nlohmann/json
197//
198// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
199// SPDX-License-Identifier: MIT
200
201
202
203#include <array> // array
204#include <cstddef> // size_t
205#include <cstdint> // uint8_t
206#include <string> // string
207
208// #include <nlohmann/detail/macro_scope.hpp>
209// __ _____ _____ _____
210// __| | __| | | | JSON for Modern C++
211// | | |__ | | | | | | version 3.11.3
212// |_____|_____|_____|_|___| https://github.com/nlohmann/json
213//
214// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
215// SPDX-License-Identifier: MIT
216
217
218
219#include <utility> // declval, pair
220// #include <nlohmann/detail/meta/detected.hpp>
221// __ _____ _____ _____
222// __| | __| | | | JSON for Modern C++
223// | | |__ | | | | | | version 3.11.3
224// |_____|_____|_____|_|___| https://github.com/nlohmann/json
225//
226// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
227// SPDX-License-Identifier: MIT
228
229
230
231#include <type_traits>
232
233// #include <nlohmann/detail/meta/void_t.hpp>
234// __ _____ _____ _____
235// __| | __| | | | JSON for Modern C++
236// | | |__ | | | | | | version 3.11.3
237// |_____|_____|_____|_|___| https://github.com/nlohmann/json
238//
239// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
240// SPDX-License-Identifier: MIT
241
242
243
244// #include <nlohmann/detail/abi_macros.hpp>
245
246
248namespace detail
249{
250
251 template<typename ...Ts> struct make_void
252 {
253 using type = void;
254 };
255 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
256
257} // namespace detail
259
260
262namespace detail
263{
264
265 // https://en.cppreference.com/w/cpp/experimental/is_detected
266 struct nonesuch
267 {
268 nonesuch() = delete;
269 ~nonesuch() = delete;
270 nonesuch(nonesuch const&) = delete;
271 nonesuch(nonesuch const&&) = delete;
272 void operator=(nonesuch const&) = delete;
273 void operator=(nonesuch&&) = delete;
274 };
275
276 template<class Default,
277 class AlwaysVoid,
278 template<class...> class Op,
279 class... Args>
280 struct detector
281 {
282 using value_t = std::false_type;
283 using type = Default;
284 };
285
286 template<class Default, template<class...> class Op, class... Args>
287 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
288 {
289 using value_t = std::true_type;
290 using type = Op<Args...>;
291 };
292
293 template<template<class...> class Op, class... Args>
294 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
295
296 template<template<class...> class Op, class... Args>
297 struct is_detected_lazy : is_detected<Op, Args...> { };
298
299 template<template<class...> class Op, class... Args>
300 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
301
302 template<class Default, template<class...> class Op, class... Args>
303 using detected_or = detector<Default, void, Op, Args...>;
304
305 template<class Default, template<class...> class Op, class... Args>
306 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
307
308 template<class Expected, template<class...> class Op, class... Args>
309 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
310
311 template<class To, template<class...> class Op, class... Args>
313 std::is_convertible<detected_t<Op, Args...>, To>;
314
315} // namespace detail
317
318// #include <nlohmann/thirdparty/hedley/hedley.hpp>
319
320
321// __ _____ _____ _____
322// __| | __| | | | JSON for Modern C++
323// | | |__ | | | | | | version 3.11.3
324// |_____|_____|_____|_|___| https://github.com/nlohmann/json
325//
326// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
327// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
328// SPDX-License-Identifier: MIT
329
330/* Hedley - https://nemequ.github.io/hedley
331 * Created by Evan Nemerson <evan@nemerson.com>
332 */
333
334#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
335#if defined(JSON_HEDLEY_VERSION)
336#undef JSON_HEDLEY_VERSION
337#endif
338#define JSON_HEDLEY_VERSION 15
339
340#if defined(JSON_HEDLEY_STRINGIFY_EX)
341#undef JSON_HEDLEY_STRINGIFY_EX
342#endif
343#define JSON_HEDLEY_STRINGIFY_EX(x) #x
344
345#if defined(JSON_HEDLEY_STRINGIFY)
346#undef JSON_HEDLEY_STRINGIFY
347#endif
348#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
349
350#if defined(JSON_HEDLEY_CONCAT_EX)
351#undef JSON_HEDLEY_CONCAT_EX
352#endif
353#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
354
355#if defined(JSON_HEDLEY_CONCAT)
356#undef JSON_HEDLEY_CONCAT
357#endif
358#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
359
360#if defined(JSON_HEDLEY_CONCAT3_EX)
361#undef JSON_HEDLEY_CONCAT3_EX
362#endif
363#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
364
365#if defined(JSON_HEDLEY_CONCAT3)
366#undef JSON_HEDLEY_CONCAT3
367#endif
368#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
369
370#if defined(JSON_HEDLEY_VERSION_ENCODE)
371#undef JSON_HEDLEY_VERSION_ENCODE
372#endif
373#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
374
375#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
376#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
377#endif
378#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
379
380#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
381#undef JSON_HEDLEY_VERSION_DECODE_MINOR
382#endif
383#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
384
385#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
386#undef JSON_HEDLEY_VERSION_DECODE_REVISION
387#endif
388#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
389
390#if defined(JSON_HEDLEY_GNUC_VERSION)
391#undef JSON_HEDLEY_GNUC_VERSION
392#endif
393#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
394#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
395#elif defined(__GNUC__)
396#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
397#endif
398
399#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
400#undef JSON_HEDLEY_GNUC_VERSION_CHECK
401#endif
402#if defined(JSON_HEDLEY_GNUC_VERSION)
403#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
404#else
405#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
406#endif
407
408#if defined(JSON_HEDLEY_MSVC_VERSION)
409#undef JSON_HEDLEY_MSVC_VERSION
410#endif
411#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
412#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
413#elif defined(_MSC_FULL_VER) && !defined(__ICL)
414#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
415#elif defined(_MSC_VER) && !defined(__ICL)
416#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
417#endif
418
419#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
420#undef JSON_HEDLEY_MSVC_VERSION_CHECK
421#endif
422#if !defined(JSON_HEDLEY_MSVC_VERSION)
423#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
424#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
425#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
426#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
427#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
428#else
429#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
430#endif
431
432#if defined(JSON_HEDLEY_INTEL_VERSION)
433#undef JSON_HEDLEY_INTEL_VERSION
434#endif
435#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
436#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
437#elif defined(__INTEL_COMPILER) && !defined(__ICL)
438#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
439#endif
440
441#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
442#undef JSON_HEDLEY_INTEL_VERSION_CHECK
443#endif
444#if defined(JSON_HEDLEY_INTEL_VERSION)
445#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
446#else
447#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
448#endif
449
450#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
451#undef JSON_HEDLEY_INTEL_CL_VERSION
452#endif
453#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
454#define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
455#endif
456
457#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
458#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
459#endif
460#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
461#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
462#else
463#define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
464#endif
465
466#if defined(JSON_HEDLEY_PGI_VERSION)
467#undef JSON_HEDLEY_PGI_VERSION
468#endif
469#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
470#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
471#endif
472
473#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
474#undef JSON_HEDLEY_PGI_VERSION_CHECK
475#endif
476#if defined(JSON_HEDLEY_PGI_VERSION)
477#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
478#else
479#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
480#endif
481
482#if defined(JSON_HEDLEY_SUNPRO_VERSION)
483#undef JSON_HEDLEY_SUNPRO_VERSION
484#endif
485#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
486#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
487#elif defined(__SUNPRO_C)
488#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
489#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
490#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
491#elif defined(__SUNPRO_CC)
492#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
493#endif
494
495#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
496#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
497#endif
498#if defined(JSON_HEDLEY_SUNPRO_VERSION)
499#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
500#else
501#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
502#endif
503
504#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
505#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
506#endif
507#if defined(__EMSCRIPTEN__)
508#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
509#endif
510
511#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
512#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
513#endif
514#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
515#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
516#else
517#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
518#endif
519
520#if defined(JSON_HEDLEY_ARM_VERSION)
521#undef JSON_HEDLEY_ARM_VERSION
522#endif
523#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
524#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
525#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
526#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
527#endif
528
529#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
530#undef JSON_HEDLEY_ARM_VERSION_CHECK
531#endif
532#if defined(JSON_HEDLEY_ARM_VERSION)
533#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
534#else
535#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
536#endif
537
538#if defined(JSON_HEDLEY_IBM_VERSION)
539#undef JSON_HEDLEY_IBM_VERSION
540#endif
541#if defined(__ibmxl__)
542#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
543#elif defined(__xlC__) && defined(__xlC_ver__)
544#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
545#elif defined(__xlC__)
546#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
547#endif
548
549#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
550#undef JSON_HEDLEY_IBM_VERSION_CHECK
551#endif
552#if defined(JSON_HEDLEY_IBM_VERSION)
553#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
554#else
555#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
556#endif
557
558#if defined(JSON_HEDLEY_TI_VERSION)
559#undef JSON_HEDLEY_TI_VERSION
560#endif
561#if \
562 defined(__TI_COMPILER_VERSION__) && \
563 ( \
564 defined(__TMS470__) || defined(__TI_ARM__) || \
565 defined(__MSP430__) || \
566 defined(__TMS320C2000__) \
567 )
568#if (__TI_COMPILER_VERSION__ >= 16000000)
569#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
570#endif
571#endif
572
573#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
574#undef JSON_HEDLEY_TI_VERSION_CHECK
575#endif
576#if defined(JSON_HEDLEY_TI_VERSION)
577#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
578#else
579#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
580#endif
581
582#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
583#undef JSON_HEDLEY_TI_CL2000_VERSION
584#endif
585#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
586#define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
587#endif
588
589#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
590#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
591#endif
592#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
593#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
594#else
595#define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
596#endif
597
598#if defined(JSON_HEDLEY_TI_CL430_VERSION)
599#undef JSON_HEDLEY_TI_CL430_VERSION
600#endif
601#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
602#define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
603#endif
604
605#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
606#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
607#endif
608#if defined(JSON_HEDLEY_TI_CL430_VERSION)
609#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
610#else
611#define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
612#endif
613
614#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
615#undef JSON_HEDLEY_TI_ARMCL_VERSION
616#endif
617#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
618#define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
619#endif
620
621#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
622#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
623#endif
624#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
625#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
626#else
627#define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
628#endif
629
630#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
631#undef JSON_HEDLEY_TI_CL6X_VERSION
632#endif
633#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
634#define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
635#endif
636
637#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
638#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
639#endif
640#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
641#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
642#else
643#define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
644#endif
645
646#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
647#undef JSON_HEDLEY_TI_CL7X_VERSION
648#endif
649#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
650#define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
651#endif
652
653#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
654#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
655#endif
656#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
657#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
658#else
659#define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
660#endif
661
662#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
663#undef JSON_HEDLEY_TI_CLPRU_VERSION
664#endif
665#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
666#define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
667#endif
668
669#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
670#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
671#endif
672#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
673#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
674#else
675#define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
676#endif
677
678#if defined(JSON_HEDLEY_CRAY_VERSION)
679#undef JSON_HEDLEY_CRAY_VERSION
680#endif
681#if defined(_CRAYC)
682#if defined(_RELEASE_PATCHLEVEL)
683#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
684#else
685#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
686#endif
687#endif
688
689#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
690#undef JSON_HEDLEY_CRAY_VERSION_CHECK
691#endif
692#if defined(JSON_HEDLEY_CRAY_VERSION)
693#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
694#else
695#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
696#endif
697
698#if defined(JSON_HEDLEY_IAR_VERSION)
699#undef JSON_HEDLEY_IAR_VERSION
700#endif
701#if defined(__IAR_SYSTEMS_ICC__)
702#if __VER__ > 1000
703#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
704#else
705#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
706#endif
707#endif
708
709#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
710#undef JSON_HEDLEY_IAR_VERSION_CHECK
711#endif
712#if defined(JSON_HEDLEY_IAR_VERSION)
713#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
714#else
715#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
716#endif
717
718#if defined(JSON_HEDLEY_TINYC_VERSION)
719#undef JSON_HEDLEY_TINYC_VERSION
720#endif
721#if defined(__TINYC__)
722#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
723#endif
724
725#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
726#undef JSON_HEDLEY_TINYC_VERSION_CHECK
727#endif
728#if defined(JSON_HEDLEY_TINYC_VERSION)
729#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
730#else
731#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
732#endif
733
734#if defined(JSON_HEDLEY_DMC_VERSION)
735#undef JSON_HEDLEY_DMC_VERSION
736#endif
737#if defined(__DMC__)
738#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
739#endif
740
741#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
742#undef JSON_HEDLEY_DMC_VERSION_CHECK
743#endif
744#if defined(JSON_HEDLEY_DMC_VERSION)
745#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
746#else
747#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
748#endif
749
750#if defined(JSON_HEDLEY_COMPCERT_VERSION)
751#undef JSON_HEDLEY_COMPCERT_VERSION
752#endif
753#if defined(__COMPCERT_VERSION__)
754#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
755#endif
756
757#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
758#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
759#endif
760#if defined(JSON_HEDLEY_COMPCERT_VERSION)
761#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
762#else
763#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
764#endif
765
766#if defined(JSON_HEDLEY_PELLES_VERSION)
767#undef JSON_HEDLEY_PELLES_VERSION
768#endif
769#if defined(__POCC__)
770#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
771#endif
772
773#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
774#undef JSON_HEDLEY_PELLES_VERSION_CHECK
775#endif
776#if defined(JSON_HEDLEY_PELLES_VERSION)
777#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
778#else
779#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
780#endif
781
782#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
783#undef JSON_HEDLEY_MCST_LCC_VERSION
784#endif
785#if defined(__LCC__) && defined(__LCC_MINOR__)
786#define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
787#endif
788
789#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
790#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
791#endif
792#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
793#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
794#else
795#define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
796#endif
797
798#if defined(JSON_HEDLEY_GCC_VERSION)
799#undef JSON_HEDLEY_GCC_VERSION
800#endif
801#if \
802 defined(JSON_HEDLEY_GNUC_VERSION) && \
803 !defined(__clang__) && \
804 !defined(JSON_HEDLEY_INTEL_VERSION) && \
805 !defined(JSON_HEDLEY_PGI_VERSION) && \
806 !defined(JSON_HEDLEY_ARM_VERSION) && \
807 !defined(JSON_HEDLEY_CRAY_VERSION) && \
808 !defined(JSON_HEDLEY_TI_VERSION) && \
809 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
810 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
811 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
812 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
813 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
814 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
815 !defined(__COMPCERT__) && \
816 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
817#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
818#endif
819
820#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
821#undef JSON_HEDLEY_GCC_VERSION_CHECK
822#endif
823#if defined(JSON_HEDLEY_GCC_VERSION)
824#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
825#else
826#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
827#endif
828
829#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
830#undef JSON_HEDLEY_HAS_ATTRIBUTE
831#endif
832#if \
833 defined(__has_attribute) && \
834 ( \
835 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
836 )
837# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
838#else
839# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
840#endif
841
842#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
843#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
844#endif
845#if defined(__has_attribute)
846#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
847#else
848#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
849#endif
850
851#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
852#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
853#endif
854#if defined(__has_attribute)
855#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
856#else
857#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
858#endif
859
860#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
861#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
862#endif
863#if \
864 defined(__has_cpp_attribute) && \
865 defined(__cplusplus) && \
866 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
867#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
868#else
869#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
870#endif
871
872#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
873#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
874#endif
875#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
876#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
877#elif \
878 !defined(JSON_HEDLEY_PGI_VERSION) && \
879 !defined(JSON_HEDLEY_IAR_VERSION) && \
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
881 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
882#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
883#else
884#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
885#endif
886
887#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
888#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
889#endif
890#if defined(__has_cpp_attribute) && defined(__cplusplus)
891#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
892#else
893#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
894#endif
895
896#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
897#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
898#endif
899#if defined(__has_cpp_attribute) && defined(__cplusplus)
900#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
901#else
902#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
903#endif
904
905#if defined(JSON_HEDLEY_HAS_BUILTIN)
906#undef JSON_HEDLEY_HAS_BUILTIN
907#endif
908#if defined(__has_builtin)
909#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
910#else
911#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
912#endif
913
914#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
915#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
916#endif
917#if defined(__has_builtin)
918#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
919#else
920#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
921#endif
922
923#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
924#undef JSON_HEDLEY_GCC_HAS_BUILTIN
925#endif
926#if defined(__has_builtin)
927#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
928#else
929#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
930#endif
931
932#if defined(JSON_HEDLEY_HAS_FEATURE)
933#undef JSON_HEDLEY_HAS_FEATURE
934#endif
935#if defined(__has_feature)
936#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
937#else
938#define JSON_HEDLEY_HAS_FEATURE(feature) (0)
939#endif
940
941#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
942#undef JSON_HEDLEY_GNUC_HAS_FEATURE
943#endif
944#if defined(__has_feature)
945#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
946#else
947#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
948#endif
949
950#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
951#undef JSON_HEDLEY_GCC_HAS_FEATURE
952#endif
953#if defined(__has_feature)
954#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
955#else
956#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
957#endif
958
959#if defined(JSON_HEDLEY_HAS_EXTENSION)
960#undef JSON_HEDLEY_HAS_EXTENSION
961#endif
962#if defined(__has_extension)
963#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
964#else
965#define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
966#endif
967
968#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
969#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
970#endif
971#if defined(__has_extension)
972#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
973#else
974#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
975#endif
976
977#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
978#undef JSON_HEDLEY_GCC_HAS_EXTENSION
979#endif
980#if defined(__has_extension)
981#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
982#else
983#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
984#endif
985
986#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
987#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
988#endif
989#if defined(__has_declspec_attribute)
990#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
991#else
992#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
993#endif
994
995#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
996#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
997#endif
998#if defined(__has_declspec_attribute)
999#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1000#else
1001#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1002#endif
1003
1004#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1005#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1006#endif
1007#if defined(__has_declspec_attribute)
1008#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1009#else
1010#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1011#endif
1012
1013#if defined(JSON_HEDLEY_HAS_WARNING)
1014#undef JSON_HEDLEY_HAS_WARNING
1015#endif
1016#if defined(__has_warning)
1017#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1018#else
1019#define JSON_HEDLEY_HAS_WARNING(warning) (0)
1020#endif
1021
1022#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1023#undef JSON_HEDLEY_GNUC_HAS_WARNING
1024#endif
1025#if defined(__has_warning)
1026#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1027#else
1028#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1029#endif
1030
1031#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1032#undef JSON_HEDLEY_GCC_HAS_WARNING
1033#endif
1034#if defined(__has_warning)
1035#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1036#else
1037#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1038#endif
1039
1040#if \
1041 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1042 defined(__clang__) || \
1043 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1044 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1045 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1046 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1047 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1048 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1049 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1050 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1051 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1052 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1053 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1054 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1055 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1056 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1057 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1058 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1059#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1060#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1061#define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1062#else
1063#define JSON_HEDLEY_PRAGMA(value)
1064#endif
1065
1066#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1067#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1068#endif
1069#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1070#undef JSON_HEDLEY_DIAGNOSTIC_POP
1071#endif
1072#if defined(__clang__)
1073#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1074#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1075#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1076#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1077#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1078#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1079#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1080#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1081#elif \
1082 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1083 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1084#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1085#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1086#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1087#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1088#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1089#elif \
1090 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1091 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1092 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1094 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1095 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1096#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1097#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1098#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1099#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1100#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1101#else
1102#define JSON_HEDLEY_DIAGNOSTIC_PUSH
1103#define JSON_HEDLEY_DIAGNOSTIC_POP
1104#endif
1105
1106 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1107 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1108#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1109#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1110#endif
1111#if defined(__cplusplus)
1112# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1113# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1114# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1115# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1116 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1117 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1118 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1119 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1120 xpr \
1121 JSON_HEDLEY_DIAGNOSTIC_POP
1122# else
1123# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1124 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1125 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1126 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1127 xpr \
1128 JSON_HEDLEY_DIAGNOSTIC_POP
1129# endif
1130# else
1131# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1132 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1133 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1134 xpr \
1135 JSON_HEDLEY_DIAGNOSTIC_POP
1136# endif
1137# endif
1138#endif
1139#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1140#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1141#endif
1142
1143#if defined(JSON_HEDLEY_CONST_CAST)
1144#undef JSON_HEDLEY_CONST_CAST
1145#endif
1146#if defined(__cplusplus)
1147# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1148#elif \
1149 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1150 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1151 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1152# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1153 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1154 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1155 ((T) (expr)); \
1156 JSON_HEDLEY_DIAGNOSTIC_POP \
1157 }))
1158#else
1159# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1160#endif
1161
1162#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1163#undef JSON_HEDLEY_REINTERPRET_CAST
1164#endif
1165#if defined(__cplusplus)
1166#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1167#else
1168#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1169#endif
1170
1171#if defined(JSON_HEDLEY_STATIC_CAST)
1172#undef JSON_HEDLEY_STATIC_CAST
1173#endif
1174#if defined(__cplusplus)
1175#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1176#else
1177#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1178#endif
1179
1180#if defined(JSON_HEDLEY_CPP_CAST)
1181#undef JSON_HEDLEY_CPP_CAST
1182#endif
1183#if defined(__cplusplus)
1184# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1185# define JSON_HEDLEY_CPP_CAST(T, expr) \
1186 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1187 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1188 ((T) (expr)) \
1189 JSON_HEDLEY_DIAGNOSTIC_POP
1190# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1191# define JSON_HEDLEY_CPP_CAST(T, expr) \
1192 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1193 _Pragma("diag_suppress=Pe137") \
1194 JSON_HEDLEY_DIAGNOSTIC_POP
1195# else
1196# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1197# endif
1198#else
1199# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1200#endif
1201
1202#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1203#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1204#endif
1205#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1206#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1207#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1208#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1209#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1210#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1211#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1212#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1213#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1214#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1215#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1216#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1217#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1218#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1219#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1220#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1221#elif \
1222 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1223 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1224 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1225 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1226 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1227 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1228 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1229 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1230 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1231 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1232 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1233#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1234#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1235#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1236#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1237#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1238#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1239#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1240#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1241#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1242#else
1243#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1244#endif
1245
1246#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1247#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1248#endif
1249#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1250#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1251#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1252#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1253#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1254#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1255#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1256#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1257#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1258#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1259#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1260#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1261#elif \
1262 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1263 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1264 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1265 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1266#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1267#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1268#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1269#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1270#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1271#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1272#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1273#else
1274#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1275#endif
1276
1277#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1278#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1279#endif
1280#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1281#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1282#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1283#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1284#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1285#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1286#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1287#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1288#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1289#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1290#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1291#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1292#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1293#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1294#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1295#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1296#elif \
1297 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1298 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1299 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1300#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1301#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1302#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1303#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1304#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1305#else
1306#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1307#endif
1308
1309#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1310#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1311#endif
1312#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1313#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1314#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1315#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1316#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1317#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1318#else
1319#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1320#endif
1321
1322#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1323#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1324#endif
1325#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1326#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1327#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1328#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1329#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1330#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1331#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1332#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1333#else
1334#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1335#endif
1336
1337#if defined(JSON_HEDLEY_DEPRECATED)
1338#undef JSON_HEDLEY_DEPRECATED
1339#endif
1340#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1341#undef JSON_HEDLEY_DEPRECATED_FOR
1342#endif
1343#if \
1344 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1345 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1346#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1347#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1348#elif \
1349 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1350 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1351 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1352 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1353 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1354 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1355 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1356 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1357 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1358 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1359 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1360 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1361#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1362#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1363#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1364#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1365#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1366#elif \
1367 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1368 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1369 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1370 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1371 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1372 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1373 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1374 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1375 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1376 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1377 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1378 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1379 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1380 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1381 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1382 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1383#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1384#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1385#elif \
1386 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1387 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1388 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1389#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1390#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1391#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1392#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1393#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1394#else
1395#define JSON_HEDLEY_DEPRECATED(since)
1396#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1397#endif
1398
1399#if defined(JSON_HEDLEY_UNAVAILABLE)
1400#undef JSON_HEDLEY_UNAVAILABLE
1401#endif
1402#if \
1403 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1404 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1405 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1406 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1407#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1408#else
1409#define JSON_HEDLEY_UNAVAILABLE(available_since)
1410#endif
1411
1412#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1413#undef JSON_HEDLEY_WARN_UNUSED_RESULT
1414#endif
1415#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1416#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1417#endif
1418#if \
1419 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1420 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1421 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1422 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1423 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1424 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1425 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1426 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1427 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1428 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1429 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1430 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1431 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1432 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1433 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1434 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1435 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1436#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1437#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1438#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1439#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1440#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1441#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1442#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1443#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1444#elif defined(_Check_return_) /* SAL */
1445#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1446#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1447#else
1448#define JSON_HEDLEY_WARN_UNUSED_RESULT
1449#define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1450#endif
1451
1452#if defined(JSON_HEDLEY_SENTINEL)
1453#undef JSON_HEDLEY_SENTINEL
1454#endif
1455#if \
1456 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1457 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1458 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1459 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1460 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1461#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1462#else
1463#define JSON_HEDLEY_SENTINEL(position)
1464#endif
1465
1466#if defined(JSON_HEDLEY_NO_RETURN)
1467#undef JSON_HEDLEY_NO_RETURN
1468#endif
1469#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1470#define JSON_HEDLEY_NO_RETURN __noreturn
1471#elif \
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1474#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1475#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1476#define JSON_HEDLEY_NO_RETURN _Noreturn
1477#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1478#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1479#elif \
1480 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1481 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1482 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1483 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1484 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1485 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1486 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1487 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1488 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1489 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1490 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1491 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1492 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1493 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1494 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1495 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1496 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1497#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1498#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1499#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1500#elif \
1501 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1502 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1503#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1504#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1505#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1506#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1507#define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1508#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1509#define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1510#else
1511#define JSON_HEDLEY_NO_RETURN
1512#endif
1513
1514#if defined(JSON_HEDLEY_NO_ESCAPE)
1515#undef JSON_HEDLEY_NO_ESCAPE
1516#endif
1517#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1518#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1519#else
1520#define JSON_HEDLEY_NO_ESCAPE
1521#endif
1522
1523#if defined(JSON_HEDLEY_UNREACHABLE)
1524#undef JSON_HEDLEY_UNREACHABLE
1525#endif
1526#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1527#undef JSON_HEDLEY_UNREACHABLE_RETURN
1528#endif
1529#if defined(JSON_HEDLEY_ASSUME)
1530#undef JSON_HEDLEY_ASSUME
1531#endif
1532#if \
1533 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1534 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1535 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1536#define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1537#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1538#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1539#elif \
1540 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1541 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1542#if defined(__cplusplus)
1543#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1544#else
1545#define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1546#endif
1547#endif
1548#if \
1549 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1550 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1551 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1552 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1553 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1554 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1555 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1556#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1557#elif defined(JSON_HEDLEY_ASSUME)
1558#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1559#endif
1560#if !defined(JSON_HEDLEY_ASSUME)
1561#if defined(JSON_HEDLEY_UNREACHABLE)
1562#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1563#else
1564#define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1565#endif
1566#endif
1567#if defined(JSON_HEDLEY_UNREACHABLE)
1568#if \
1569 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1570 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1571#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1572#else
1573#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1574#endif
1575#else
1576#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1577#endif
1578#if !defined(JSON_HEDLEY_UNREACHABLE)
1579#define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1580#endif
1581
1583#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1584#pragma clang diagnostic ignored "-Wpedantic"
1585#endif
1586#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1587#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1588#endif
1589#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1590#if defined(__clang__)
1591#pragma clang diagnostic ignored "-Wvariadic-macros"
1592#elif defined(JSON_HEDLEY_GCC_VERSION)
1593#pragma GCC diagnostic ignored "-Wvariadic-macros"
1594#endif
1595#endif
1596#if defined(JSON_HEDLEY_NON_NULL)
1597#undef JSON_HEDLEY_NON_NULL
1598#endif
1599#if \
1600 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1601 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1602 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1603 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1604#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1605#else
1606#define JSON_HEDLEY_NON_NULL(...)
1607#endif
1609
1610#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1611#undef JSON_HEDLEY_PRINTF_FORMAT
1612#endif
1613#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1614#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1615#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1616#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1617#elif \
1618 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1619 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1620 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1621 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1622 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1623 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1624 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1625 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1626 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1627 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1628 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1629 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1630 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1631 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1632 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1633 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1634 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1635#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1636#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1637#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1638#else
1639#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1640#endif
1641
1642#if defined(JSON_HEDLEY_CONSTEXPR)
1643#undef JSON_HEDLEY_CONSTEXPR
1644#endif
1645#if defined(__cplusplus)
1646#if __cplusplus >= 201103L
1647#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1648#endif
1649#endif
1650#if !defined(JSON_HEDLEY_CONSTEXPR)
1651#define JSON_HEDLEY_CONSTEXPR
1652#endif
1653
1654#if defined(JSON_HEDLEY_PREDICT)
1655#undef JSON_HEDLEY_PREDICT
1656#endif
1657#if defined(JSON_HEDLEY_LIKELY)
1658#undef JSON_HEDLEY_LIKELY
1659#endif
1660#if defined(JSON_HEDLEY_UNLIKELY)
1661#undef JSON_HEDLEY_UNLIKELY
1662#endif
1663#if defined(JSON_HEDLEY_UNPREDICTABLE)
1664#undef JSON_HEDLEY_UNPREDICTABLE
1665#endif
1666#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1667#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1668#endif
1669#if \
1670 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1671 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1672 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1673# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1674# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1675# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1676# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1677# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1678#elif \
1679 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1680 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1681 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1682 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1683 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1684 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1685 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1686 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1687 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1688 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1689 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1690 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1691 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1692 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1693 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1694 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1695# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1696 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1697# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1698 (__extension__ ({ \
1699 double hedley_probability_ = (probability); \
1700 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1701 }))
1702# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1703 (__extension__ ({ \
1704 double hedley_probability_ = (probability); \
1705 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1706 }))
1707# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1708# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1709#else
1710# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1711# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1712# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1713# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1714# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1715#endif
1716#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1717#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1718#endif
1719
1720#if defined(JSON_HEDLEY_MALLOC)
1721#undef JSON_HEDLEY_MALLOC
1722#endif
1723#if \
1724 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1725 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1726 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1727 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1728 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1729 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1730 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1731 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1732 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1733 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1734 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1735 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1736 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1737 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1738 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1739 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1740 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1741 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1742#define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1743#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1744#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1745#elif \
1746 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1747 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1748#define JSON_HEDLEY_MALLOC __declspec(restrict)
1749#else
1750#define JSON_HEDLEY_MALLOC
1751#endif
1752
1753#if defined(JSON_HEDLEY_PURE)
1754#undef JSON_HEDLEY_PURE
1755#endif
1756#if \
1757 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1758 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1759 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1760 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1761 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1762 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1763 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1764 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1765 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1766 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1767 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1768 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1769 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1770 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1771 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1772 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1773 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1774 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1775 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1776# define JSON_HEDLEY_PURE __attribute__((__pure__))
1777#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1778# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1779#elif defined(__cplusplus) && \
1780 ( \
1781 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1784 )
1785# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1786#else
1787# define JSON_HEDLEY_PURE
1788#endif
1789
1790#if defined(JSON_HEDLEY_CONST)
1791#undef JSON_HEDLEY_CONST
1792#endif
1793#if \
1794 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1795 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1796 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1797 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1798 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1799 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1800 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1801 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1802 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1803 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1804 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1805 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1806 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1807 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1808 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1809 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1810 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1811 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1812 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1813#define JSON_HEDLEY_CONST __attribute__((__const__))
1814#elif \
1815 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1816#define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1817#else
1818#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1819#endif
1820
1821#if defined(JSON_HEDLEY_RESTRICT)
1822#undef JSON_HEDLEY_RESTRICT
1823#endif
1824#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1825#define JSON_HEDLEY_RESTRICT restrict
1826#elif \
1827 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1828 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1829 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1830 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1831 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1832 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1833 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1834 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1835 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1836 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1837 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1838 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1839 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1840 defined(__clang__) || \
1841 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1842#define JSON_HEDLEY_RESTRICT __restrict
1843#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1844#define JSON_HEDLEY_RESTRICT _Restrict
1845#else
1846#define JSON_HEDLEY_RESTRICT
1847#endif
1848
1849#if defined(JSON_HEDLEY_INLINE)
1850#undef JSON_HEDLEY_INLINE
1851#endif
1852#if \
1853 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1854 (defined(__cplusplus) && (__cplusplus >= 199711L))
1855#define JSON_HEDLEY_INLINE inline
1856#elif \
1857 defined(JSON_HEDLEY_GCC_VERSION) || \
1858 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1859#define JSON_HEDLEY_INLINE __inline__
1860#elif \
1861 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1862 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1863 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1864 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1865 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1866 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1867 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1868 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1869 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1870 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1871#define JSON_HEDLEY_INLINE __inline
1872#else
1873#define JSON_HEDLEY_INLINE
1874#endif
1875
1876#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1877#undef JSON_HEDLEY_ALWAYS_INLINE
1878#endif
1879#if \
1880 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1881 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1882 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1883 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1884 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1885 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1886 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1887 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1888 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1889 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1890 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1891 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1892 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1893 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1894 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1895 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1896 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1897 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1898 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1899# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1900#elif \
1901 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1902 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1903# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1904#elif defined(__cplusplus) && \
1905 ( \
1906 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1907 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1908 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1909 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1910 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1911 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1912 )
1913# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1914#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1915# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1916#else
1917# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1918#endif
1919
1920#if defined(JSON_HEDLEY_NEVER_INLINE)
1921#undef JSON_HEDLEY_NEVER_INLINE
1922#endif
1923#if \
1924 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1925 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1926 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1927 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1928 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1929 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1930 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1931 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1932 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1933 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1934 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1935 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1936 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1937 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1938 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1939 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1940 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1941 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1942 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1943#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1944#elif \
1945 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1946 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1947#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1948#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1949#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1950#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1951#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1952#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1953#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1954#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1955#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1956#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1957#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1958#else
1959#define JSON_HEDLEY_NEVER_INLINE
1960#endif
1961
1962#if defined(JSON_HEDLEY_PRIVATE)
1963#undef JSON_HEDLEY_PRIVATE
1964#endif
1965#if defined(JSON_HEDLEY_PUBLIC)
1966#undef JSON_HEDLEY_PUBLIC
1967#endif
1968#if defined(JSON_HEDLEY_IMPORT)
1969#undef JSON_HEDLEY_IMPORT
1970#endif
1971#if defined(_WIN32) || defined(__CYGWIN__)
1972# define JSON_HEDLEY_PRIVATE
1973# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1974# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1975#else
1976# if \
1977 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1978 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1979 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1980 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1981 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1982 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1983 ( \
1984 defined(__TI_EABI__) && \
1985 ( \
1986 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1987 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1988 ) \
1989 ) || \
1990 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1991# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
1992# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
1993# else
1994# define JSON_HEDLEY_PRIVATE
1995# define JSON_HEDLEY_PUBLIC
1996# endif
1997# define JSON_HEDLEY_IMPORT extern
1998#endif
1999
2000#if defined(JSON_HEDLEY_NO_THROW)
2001#undef JSON_HEDLEY_NO_THROW
2002#endif
2003#if \
2004 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2005 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2006 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2007 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2008#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2009#elif \
2010 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2011 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2012 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2013#define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2014#else
2015#define JSON_HEDLEY_NO_THROW
2016#endif
2017
2018#if defined(JSON_HEDLEY_FALL_THROUGH)
2019#undef JSON_HEDLEY_FALL_THROUGH
2020#endif
2021#if \
2022 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2023 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2024 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2025#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2026#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2027#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2028#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2029#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2030#elif defined(__fallthrough) /* SAL */
2031#define JSON_HEDLEY_FALL_THROUGH __fallthrough
2032#else
2033#define JSON_HEDLEY_FALL_THROUGH
2034#endif
2035
2036#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2037#undef JSON_HEDLEY_RETURNS_NON_NULL
2038#endif
2039#if \
2040 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2041 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2042 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2043#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2044#elif defined(_Ret_notnull_) /* SAL */
2045#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2046#else
2047#define JSON_HEDLEY_RETURNS_NON_NULL
2048#endif
2049
2050#if defined(JSON_HEDLEY_ARRAY_PARAM)
2051#undef JSON_HEDLEY_ARRAY_PARAM
2052#endif
2053#if \
2054 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2055 !defined(__STDC_NO_VLA__) && \
2056 !defined(__cplusplus) && \
2057 !defined(JSON_HEDLEY_PGI_VERSION) && \
2058 !defined(JSON_HEDLEY_TINYC_VERSION)
2059#define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2060#else
2061#define JSON_HEDLEY_ARRAY_PARAM(name)
2062#endif
2063
2064#if defined(JSON_HEDLEY_IS_CONSTANT)
2065#undef JSON_HEDLEY_IS_CONSTANT
2066#endif
2067#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2068#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2069#endif
2070 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
2071 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2072#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2073#undef JSON_HEDLEY_IS_CONSTEXPR_
2074#endif
2075#if \
2076 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2077 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2078 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2079 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2080 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2081 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2082 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2083 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2084 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2085 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2086#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2087#endif
2088#if !defined(__cplusplus)
2089# if \
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2094 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2095 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2096 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2097#if defined(__INTPTR_TYPE__)
2098#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2099#else
2100#include <stdint.h>
2101#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2102#endif
2103# elif \
2104 ( \
2105 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2106 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2107 !defined(JSON_HEDLEY_PGI_VERSION) && \
2108 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2109 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2110 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2111 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2112 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2113 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2114#if defined(__INTPTR_TYPE__)
2115#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2116#else
2117#include <stdint.h>
2118#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2119#endif
2120# elif \
2121 defined(JSON_HEDLEY_GCC_VERSION) || \
2122 defined(JSON_HEDLEY_INTEL_VERSION) || \
2123 defined(JSON_HEDLEY_TINYC_VERSION) || \
2124 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2125 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2126 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2127 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2128 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2129 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2130 defined(__clang__)
2131# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2132 sizeof(void) != \
2133 sizeof(*( \
2134 1 ? \
2135 ((void*) ((expr) * 0L) ) : \
2136((struct { char v[sizeof(void) * 2]; } *) 1) \
2137 ) \
2138 ) \
2139 )
2140# endif
2141#endif
2142#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2143#if !defined(JSON_HEDLEY_IS_CONSTANT)
2144#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2145#endif
2146#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2147#else
2148#if !defined(JSON_HEDLEY_IS_CONSTANT)
2149#define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2150#endif
2151#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2152#endif
2153
2154#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2155#undef JSON_HEDLEY_BEGIN_C_DECLS
2156#endif
2157#if defined(JSON_HEDLEY_END_C_DECLS)
2158#undef JSON_HEDLEY_END_C_DECLS
2159#endif
2160#if defined(JSON_HEDLEY_C_DECL)
2161#undef JSON_HEDLEY_C_DECL
2162#endif
2163#if defined(__cplusplus)
2164#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2165#define JSON_HEDLEY_END_C_DECLS }
2166#define JSON_HEDLEY_C_DECL extern "C"
2167#else
2168#define JSON_HEDLEY_BEGIN_C_DECLS
2169#define JSON_HEDLEY_END_C_DECLS
2170#define JSON_HEDLEY_C_DECL
2171#endif
2172
2173#if defined(JSON_HEDLEY_STATIC_ASSERT)
2174#undef JSON_HEDLEY_STATIC_ASSERT
2175#endif
2176#if \
2177 !defined(__cplusplus) && ( \
2178 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2179 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2180 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2181 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2182 defined(_Static_assert) \
2183 )
2184# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2185#elif \
2186 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2187 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2188 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2189# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2190#else
2191# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2192#endif
2193
2194#if defined(JSON_HEDLEY_NULL)
2195#undef JSON_HEDLEY_NULL
2196#endif
2197#if defined(__cplusplus)
2198#if __cplusplus >= 201103L
2199#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2200#elif defined(NULL)
2201#define JSON_HEDLEY_NULL NULL
2202#else
2203#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2204#endif
2205#elif defined(NULL)
2206#define JSON_HEDLEY_NULL NULL
2207#else
2208#define JSON_HEDLEY_NULL ((void*) 0)
2209#endif
2210
2211#if defined(JSON_HEDLEY_MESSAGE)
2212#undef JSON_HEDLEY_MESSAGE
2213#endif
2214#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2215# define JSON_HEDLEY_MESSAGE(msg) \
2216 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2217 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2218 JSON_HEDLEY_PRAGMA(message msg) \
2219 JSON_HEDLEY_DIAGNOSTIC_POP
2220#elif \
2221 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2222 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2223# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2224#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2225# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2226#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2227# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2228#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2229# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2230#else
2231# define JSON_HEDLEY_MESSAGE(msg)
2232#endif
2233
2234#if defined(JSON_HEDLEY_WARNING)
2235#undef JSON_HEDLEY_WARNING
2236#endif
2237#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2238# define JSON_HEDLEY_WARNING(msg) \
2239 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2240 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2241 JSON_HEDLEY_PRAGMA(clang warning msg) \
2242 JSON_HEDLEY_DIAGNOSTIC_POP
2243#elif \
2244 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2245 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2246 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2247# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2248#elif \
2249 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2250 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2251# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2252#else
2253# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2254#endif
2255
2256#if defined(JSON_HEDLEY_REQUIRE)
2257#undef JSON_HEDLEY_REQUIRE
2258#endif
2259#if defined(JSON_HEDLEY_REQUIRE_MSG)
2260#undef JSON_HEDLEY_REQUIRE_MSG
2261#endif
2262#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2263# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2264# define JSON_HEDLEY_REQUIRE(expr) \
2265 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2266 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2267 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2268 JSON_HEDLEY_DIAGNOSTIC_POP
2269# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2270 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2271 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2272 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2273 JSON_HEDLEY_DIAGNOSTIC_POP
2274# else
2275# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2276# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2277# endif
2278#else
2279# define JSON_HEDLEY_REQUIRE(expr)
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2281#endif
2282
2283#if defined(JSON_HEDLEY_FLAGS)
2284#undef JSON_HEDLEY_FLAGS
2285#endif
2286#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2287#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2288#else
2289#define JSON_HEDLEY_FLAGS
2290#endif
2291
2292#if defined(JSON_HEDLEY_FLAGS_CAST)
2293#undef JSON_HEDLEY_FLAGS_CAST
2294#endif
2295#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2296# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2297 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2298 _Pragma("warning(disable:188)") \
2299 ((T) (expr)); \
2300 JSON_HEDLEY_DIAGNOSTIC_POP \
2301 }))
2302#else
2303# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2304#endif
2305
2306#if defined(JSON_HEDLEY_EMPTY_BASES)
2307#undef JSON_HEDLEY_EMPTY_BASES
2308#endif
2309#if \
2310 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2311 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2312#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2313#else
2314#define JSON_HEDLEY_EMPTY_BASES
2315#endif
2316
2317 /* Remaining macros are deprecated. */
2318
2319#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2320#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2321#endif
2322#if defined(__clang__)
2323#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2324#else
2325#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2326#endif
2327
2328#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2329#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2330#endif
2331#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2332
2333#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2334#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2335#endif
2336#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2337
2338#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2339#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2340#endif
2341#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2342
2343#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2344#undef JSON_HEDLEY_CLANG_HAS_FEATURE
2345#endif
2346#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2347
2348#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2349#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2350#endif
2351#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2352
2353#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2354#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2355#endif
2356#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2357
2358#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2359#undef JSON_HEDLEY_CLANG_HAS_WARNING
2360#endif
2361#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2362
2363#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2364
2365
2366// This file contains all internal macro definitions (except those affecting ABI)
2367// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2368
2369// #include <nlohmann/detail/abi_macros.hpp>
2370
2371
2372// exclude unsupported compilers
2373#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2374#if defined(__clang__)
2375#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2376#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2377#endif
2378#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2379#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2380#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2381#endif
2382#endif
2383#endif
2384
2385// C++ language standard detection
2386// if the user manually specified the used c++ version this is skipped
2387#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2388#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2389#define JSON_HAS_CPP_20
2390#define JSON_HAS_CPP_17
2391#define JSON_HAS_CPP_14
2392#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2393#define JSON_HAS_CPP_17
2394#define JSON_HAS_CPP_14
2395#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2396#define JSON_HAS_CPP_14
2397#endif
2398// the cpp 11 flag is always specified because it is the minimal required version
2399#define JSON_HAS_CPP_11
2400#endif
2401
2402#ifdef __has_include
2403#if __has_include(<version>)
2404#include <version>
2405#endif
2406#endif
2407
2408#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2409#ifdef JSON_HAS_CPP_17
2410#if defined(__cpp_lib_filesystem)
2411#define JSON_HAS_FILESYSTEM 1
2412#elif defined(__cpp_lib_experimental_filesystem)
2413#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2414#elif !defined(__has_include)
2415#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2416#elif __has_include(<filesystem>)
2417#define JSON_HAS_FILESYSTEM 1
2418#elif __has_include(<experimental/filesystem>)
2419#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2420#endif
2421
2422// std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2423#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2424#undef JSON_HAS_FILESYSTEM
2425#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2426#endif
2427
2428// no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2429#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2430#undef JSON_HAS_FILESYSTEM
2431#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2432#endif
2433
2434// no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2435#if defined(__clang_major__) && __clang_major__ < 7
2436#undef JSON_HAS_FILESYSTEM
2437#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2438#endif
2439
2440// no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2441#if defined(_MSC_VER) && _MSC_VER < 1914
2442#undef JSON_HAS_FILESYSTEM
2443#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2444#endif
2445
2446// no filesystem support before iOS 13
2447#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2448#undef JSON_HAS_FILESYSTEM
2449#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2450#endif
2451
2452// no filesystem support before macOS Catalina
2453#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2454#undef JSON_HAS_FILESYSTEM
2455#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2456#endif
2457#endif
2458#endif
2459
2460#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2461#define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2462#endif
2463
2464#ifndef JSON_HAS_FILESYSTEM
2465#define JSON_HAS_FILESYSTEM 0
2466#endif
2467
2468#ifndef JSON_HAS_THREE_WAY_COMPARISON
2469#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2470 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2471#define JSON_HAS_THREE_WAY_COMPARISON 1
2472#else
2473#define JSON_HAS_THREE_WAY_COMPARISON 0
2474#endif
2475#endif
2476
2477#ifndef JSON_HAS_RANGES
2478 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2479#if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2480#define JSON_HAS_RANGES 0
2481#elif defined(__cpp_lib_ranges)
2482#define JSON_HAS_RANGES 1
2483#else
2484#define JSON_HAS_RANGES 0
2485#endif
2486#endif
2487
2488#ifndef JSON_HAS_STATIC_RTTI
2489#if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2490#define JSON_HAS_STATIC_RTTI 1
2491#else
2492#define JSON_HAS_STATIC_RTTI 0
2493#endif
2494#endif
2495
2496#ifdef JSON_HAS_CPP_17
2497#define JSON_INLINE_VARIABLE inline
2498#else
2499#define JSON_INLINE_VARIABLE
2500#endif
2501
2502#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2503#define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2504#else
2505#define JSON_NO_UNIQUE_ADDRESS
2506#endif
2507
2508// disable documentation warnings on clang
2509#if defined(__clang__)
2510#pragma clang diagnostic push
2511#pragma clang diagnostic ignored "-Wdocumentation"
2512#pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2513#endif
2514
2515// allow disabling exceptions
2516#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2517#define JSON_THROW(exception) throw exception
2518#define JSON_TRY try
2519#define JSON_CATCH(exception) catch(exception)
2520#define JSON_INTERNAL_CATCH(exception) catch(exception)
2521#else
2522#include <cstdlib>
2523#define JSON_THROW(exception) std::abort()
2524#define JSON_TRY if(true)
2525#define JSON_CATCH(exception) if(false)
2526#define JSON_INTERNAL_CATCH(exception) if(false)
2527#endif
2528
2529// override exception macros
2530#if defined(JSON_THROW_USER)
2531#undef JSON_THROW
2532#define JSON_THROW JSON_THROW_USER
2533#endif
2534#if defined(JSON_TRY_USER)
2535#undef JSON_TRY
2536#define JSON_TRY JSON_TRY_USER
2537#endif
2538#if defined(JSON_CATCH_USER)
2539#undef JSON_CATCH
2540#define JSON_CATCH JSON_CATCH_USER
2541#undef JSON_INTERNAL_CATCH
2542#define JSON_INTERNAL_CATCH JSON_CATCH_USER
2543#endif
2544#if defined(JSON_INTERNAL_CATCH_USER)
2545#undef JSON_INTERNAL_CATCH
2546#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2547#endif
2548
2549// allow overriding assert
2550#if !defined(JSON_ASSERT)
2551#include <cassert> // assert
2552#define JSON_ASSERT(x) assert(x)
2553#endif
2554
2555// allow to access some private functions (needed by the test suite)
2556#if defined(JSON_TESTS_PRIVATE)
2557#define JSON_PRIVATE_UNLESS_TESTED public
2558#else
2559#define JSON_PRIVATE_UNLESS_TESTED private
2560#endif
2561
2567#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2568 template<typename BasicJsonType> \
2569 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2570 { \
2571 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2572 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2573 auto it = std::find_if(std::begin(m), std::end(m), \
2574 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2575 { \
2576 return ej_pair.first == e; \
2577 }); \
2578 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2579 } \
2580 template<typename BasicJsonType> \
2581 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2582 { \
2583 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2584 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2585 auto it = std::find_if(std::begin(m), std::end(m), \
2586 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2587 { \
2588 return ej_pair.second == j; \
2589 }); \
2590 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2591 }
2592
2593// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2594// may be removed in the future once the class is split.
2595
2596#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2597 template<template<typename, typename, typename...> class ObjectType, \
2598 template<typename, typename...> class ArrayType, \
2599 class StringType, class BooleanType, class NumberIntegerType, \
2600 class NumberUnsignedType, class NumberFloatType, \
2601 template<typename> class AllocatorType, \
2602 template<typename, typename = void> class JSONSerializer, \
2603 class BinaryType, \
2604 class CustomBaseClass>
2605
2606#define NLOHMANN_BASIC_JSON_TPL \
2607 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2608 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2609 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2610
2611// Macros to simplify conversion from/to types
2612
2613#define NLOHMANN_JSON_EXPAND( x ) x
2614#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2615#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2616 NLOHMANN_JSON_PASTE64, \
2617 NLOHMANN_JSON_PASTE63, \
2618 NLOHMANN_JSON_PASTE62, \
2619 NLOHMANN_JSON_PASTE61, \
2620 NLOHMANN_JSON_PASTE60, \
2621 NLOHMANN_JSON_PASTE59, \
2622 NLOHMANN_JSON_PASTE58, \
2623 NLOHMANN_JSON_PASTE57, \
2624 NLOHMANN_JSON_PASTE56, \
2625 NLOHMANN_JSON_PASTE55, \
2626 NLOHMANN_JSON_PASTE54, \
2627 NLOHMANN_JSON_PASTE53, \
2628 NLOHMANN_JSON_PASTE52, \
2629 NLOHMANN_JSON_PASTE51, \
2630 NLOHMANN_JSON_PASTE50, \
2631 NLOHMANN_JSON_PASTE49, \
2632 NLOHMANN_JSON_PASTE48, \
2633 NLOHMANN_JSON_PASTE47, \
2634 NLOHMANN_JSON_PASTE46, \
2635 NLOHMANN_JSON_PASTE45, \
2636 NLOHMANN_JSON_PASTE44, \
2637 NLOHMANN_JSON_PASTE43, \
2638 NLOHMANN_JSON_PASTE42, \
2639 NLOHMANN_JSON_PASTE41, \
2640 NLOHMANN_JSON_PASTE40, \
2641 NLOHMANN_JSON_PASTE39, \
2642 NLOHMANN_JSON_PASTE38, \
2643 NLOHMANN_JSON_PASTE37, \
2644 NLOHMANN_JSON_PASTE36, \
2645 NLOHMANN_JSON_PASTE35, \
2646 NLOHMANN_JSON_PASTE34, \
2647 NLOHMANN_JSON_PASTE33, \
2648 NLOHMANN_JSON_PASTE32, \
2649 NLOHMANN_JSON_PASTE31, \
2650 NLOHMANN_JSON_PASTE30, \
2651 NLOHMANN_JSON_PASTE29, \
2652 NLOHMANN_JSON_PASTE28, \
2653 NLOHMANN_JSON_PASTE27, \
2654 NLOHMANN_JSON_PASTE26, \
2655 NLOHMANN_JSON_PASTE25, \
2656 NLOHMANN_JSON_PASTE24, \
2657 NLOHMANN_JSON_PASTE23, \
2658 NLOHMANN_JSON_PASTE22, \
2659 NLOHMANN_JSON_PASTE21, \
2660 NLOHMANN_JSON_PASTE20, \
2661 NLOHMANN_JSON_PASTE19, \
2662 NLOHMANN_JSON_PASTE18, \
2663 NLOHMANN_JSON_PASTE17, \
2664 NLOHMANN_JSON_PASTE16, \
2665 NLOHMANN_JSON_PASTE15, \
2666 NLOHMANN_JSON_PASTE14, \
2667 NLOHMANN_JSON_PASTE13, \
2668 NLOHMANN_JSON_PASTE12, \
2669 NLOHMANN_JSON_PASTE11, \
2670 NLOHMANN_JSON_PASTE10, \
2671 NLOHMANN_JSON_PASTE9, \
2672 NLOHMANN_JSON_PASTE8, \
2673 NLOHMANN_JSON_PASTE7, \
2674 NLOHMANN_JSON_PASTE6, \
2675 NLOHMANN_JSON_PASTE5, \
2676 NLOHMANN_JSON_PASTE4, \
2677 NLOHMANN_JSON_PASTE3, \
2678 NLOHMANN_JSON_PASTE2, \
2679 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2680#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2681#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2682#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2683#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2684#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2685#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2686#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2687#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2688#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2689#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2690#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2691#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2692#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2693#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2694#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2695#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2696#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2697#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2698#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2699#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2700#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2701#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2702#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2703#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2704#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2705#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2706#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2707#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2708#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2709#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2710#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2711#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2712#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2713#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2714#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2715#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2716#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2717#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2718#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2719#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2720#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2721#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2722#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2723#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2724#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2725#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2726#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2727#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2728#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2729#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2730#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2731#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2732#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2733#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2734#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2735#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2736#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2737#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2738#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2739#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2740#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2741#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2742#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2743
2744#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2745#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2746#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2747
2753#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2754 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2755 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2756
2757#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2758 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2759 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2760
2761#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2762 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2763
2769#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2770 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2771 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2772
2773#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2774 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2775
2776#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2777 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2778 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2779
2780// inspired from https://stackoverflow.com/a/26745591
2781// allows to call any std function as if (e.g. with begin):
2782// using std::begin; begin(x);
2783//
2784// it allows using the detected idiom to retrieve the return type
2785// of such an expression
2786#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2787 namespace detail { \
2788 using std::std_name; \
2789 \
2790 template<typename... T> \
2791 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2792 } \
2793 \
2794 namespace detail2 { \
2795 struct std_name##_tag \
2796 { \
2797 }; \
2798 \
2799 template<typename... T> \
2800 std_name##_tag std_name(T&&...); \
2801 \
2802 template<typename... T> \
2803 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2804 \
2805 template<typename... T> \
2806 struct would_call_std_##std_name \
2807 { \
2808 static constexpr auto const value = ::nlohmann::detail:: \
2809 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2810 }; \
2811 } /* namespace detail2 */ \
2812 \
2813 template<typename... T> \
2814 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2815 { \
2816 }
2817
2818#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2819#define JSON_USE_IMPLICIT_CONVERSIONS 1
2820#endif
2821
2822#if JSON_USE_IMPLICIT_CONVERSIONS
2823#define JSON_EXPLICIT
2824#else
2825#define JSON_EXPLICIT explicit
2826#endif
2827
2828#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2829#define JSON_DISABLE_ENUM_SERIALIZATION 0
2830#endif
2831
2832#ifndef JSON_USE_GLOBAL_UDLS
2833#define JSON_USE_GLOBAL_UDLS 1
2834#endif
2835
2836#if JSON_HAS_THREE_WAY_COMPARISON
2837#include <compare> // partial_ordering
2838#endif
2839
2841namespace detail
2842{
2843
2845 // JSON type enumeration //
2847
2872 enum class value_t : std::uint8_t
2873 {
2874 null,
2875 object,
2876 array,
2877 string,
2878 boolean,
2881 number_float,
2882 binary,
2883 discarded
2884 };
2885
2899#if JSON_HAS_THREE_WAY_COMPARISON
2900 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2901#else
2902 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2903#endif
2904 {
2905 static constexpr std::array<std::uint8_t, 9> order = { {
2906 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2907 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2908 6 /* binary */
2909 }
2910 };
2911
2912 const auto l_index = static_cast<std::size_t>(lhs);
2913 const auto r_index = static_cast<std::size_t>(rhs);
2914#if JSON_HAS_THREE_WAY_COMPARISON
2915 if (l_index < order.size() && r_index < order.size())
2916 {
2917 return order[l_index] <=> order[r_index]; // *NOPAD*
2918 }
2919 return std::partial_ordering::unordered;
2920#else
2921 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2922#endif
2923 }
2924
2925 // GCC selects the built-in operator< over an operator rewritten from
2926 // a user-defined spaceship operator
2927 // Clang, MSVC, and ICC select the rewritten candidate
2928 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2929#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2930 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2931 {
2932 return std::is_lt(lhs <=> rhs); // *NOPAD*
2933 }
2934#endif
2935
2936} // namespace detail
2938
2939// #include <nlohmann/detail/string_escape.hpp>
2940// __ _____ _____ _____
2941// __| | __| | | | JSON for Modern C++
2942// | | |__ | | | | | | version 3.11.3
2943// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2944//
2945// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
2946// SPDX-License-Identifier: MIT
2947
2948
2949
2950// #include <nlohmann/detail/abi_macros.hpp>
2951
2952
2954namespace detail
2955{
2956
2970 template<typename StringType>
2971 inline void replace_substring(StringType& s, const StringType& f,
2972 const StringType& t)
2973 {
2974 JSON_ASSERT(!f.empty());
2975 for (auto pos = s.find(f); // find first occurrence of f
2976 pos != StringType::npos; // make sure f was found
2977 s.replace(pos, f.size(), t), // replace with t, and
2978 pos = s.find(f, pos + t.size())) // find next occurrence of f
2979 {
2980 }
2981 }
2982
2990 template<typename StringType>
2991 inline StringType escape(StringType s)
2992 {
2993 replace_substring(s, StringType{ "~" }, StringType{ "~0" });
2994 replace_substring(s, StringType{ "/" }, StringType{ "~1" });
2995 return s;
2996 }
2997
3005 template<typename StringType>
3006 static void unescape(StringType& s)
3007 {
3008 replace_substring(s, StringType{ "~1" }, StringType{ "/" });
3009 replace_substring(s, StringType{ "~0" }, StringType{ "~" });
3010 }
3011
3012} // namespace detail
3014
3015// #include <nlohmann/detail/input/position_t.hpp>
3016// __ _____ _____ _____
3017// __| | __| | | | JSON for Modern C++
3018// | | |__ | | | | | | version 3.11.3
3019// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3020//
3021// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3022// SPDX-License-Identifier: MIT
3023
3024
3025
3026#include <cstddef> // size_t
3027
3028// #include <nlohmann/detail/abi_macros.hpp>
3029
3030
3032namespace detail
3033{
3034
3037 {
3039 std::size_t chars_read_total = 0;
3043 std::size_t lines_read = 0;
3044
3046 constexpr operator size_t() const
3047 {
3048 return chars_read_total;
3049 }
3050 };
3051
3052} // namespace detail
3054
3055// #include <nlohmann/detail/macro_scope.hpp>
3056
3057// #include <nlohmann/detail/meta/cpp_future.hpp>
3058// __ _____ _____ _____
3059// __| | __| | | | JSON for Modern C++
3060// | | |__ | | | | | | version 3.11.3
3061// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3062//
3063// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3064// SPDX-FileCopyrightText: 2018 The Abseil Authors
3065// SPDX-License-Identifier: MIT
3066
3067
3068
3069#include <array> // array
3070#include <cstddef> // size_t
3071#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3072#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3073
3074// #include <nlohmann/detail/macro_scope.hpp>
3075
3076
3078namespace detail
3079{
3080
3081 template<typename T>
3082 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3083
3084#ifdef JSON_HAS_CPP_14
3085
3086 // the following utilities are natively available in C++14
3087 using std::enable_if_t;
3088 using std::index_sequence;
3089 using std::make_index_sequence;
3090 using std::index_sequence_for;
3091
3092#else
3093
3094 // alias templates to reduce boilerplate
3095 template<bool B, typename T = void>
3096 using enable_if_t = typename std::enable_if<B, T>::type;
3097
3098 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3099 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3100
3102
3103 // integer_sequence
3104 //
3105 // Class template representing a compile-time integer sequence. An instantiation
3106 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3107 // type through its template arguments (which is a common need when
3108 // working with C++11 variadic templates). `absl::integer_sequence` is designed
3109 // to be a drop-in replacement for C++14's `std::integer_sequence`.
3110 //
3111 // Example:
3112 //
3113 // template< class T, T... Ints >
3114 // void user_function(integer_sequence<T, Ints...>);
3115 //
3116 // int main()
3117 // {
3118 // // user_function's `T` will be deduced to `int` and `Ints...`
3119 // // will be deduced to `0, 1, 2, 3, 4`.
3120 // user_function(make_integer_sequence<int, 5>());
3121 // }
3122 template <typename T, T... Ints>
3124 {
3125 using value_type = T;
3126 static constexpr std::size_t size() noexcept
3127 {
3128 return sizeof...(Ints);
3129 }
3130 };
3131
3132 // index_sequence
3133 //
3134 // A helper template for an `integer_sequence` of `size_t`,
3135 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3136 // `std::index_sequence`.
3137 template <size_t... Ints>
3138 using index_sequence = integer_sequence<size_t, Ints...>;
3139
3140 namespace utility_internal
3141 {
3142
3143 template <typename Seq, size_t SeqSize, size_t Rem>
3144 struct Extend;
3145
3146 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3147 template <typename T, T... Ints, size_t SeqSize>
3148 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3149 {
3150 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3151 };
3152
3153 template <typename T, T... Ints, size_t SeqSize>
3154 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3155 {
3156 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3157 };
3158
3159 // Recursion helper for 'make_integer_sequence<T, N>'.
3160 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3161 template <typename T, size_t N>
3162 struct Gen
3163 {
3164 using type =
3165 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3166 };
3167
3168 template <typename T>
3169 struct Gen<T, 0>
3170 {
3172 };
3173
3174 } // namespace utility_internal
3175
3176 // Compile-time sequences of integers
3177
3178 // make_integer_sequence
3179 //
3180 // This template alias is equivalent to
3181 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3182 // replacement for C++14's `std::make_integer_sequence`.
3183 template <typename T, T N>
3185
3186 // make_index_sequence
3187 //
3188 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3189 // and is designed to be a drop-in replacement for C++14's
3190 // `std::make_index_sequence`.
3191 template <size_t N>
3193
3194 // index_sequence_for
3195 //
3196 // Converts a typename pack into an index sequence of the same length, and
3197 // is designed to be a drop-in replacement for C++14's
3198 // `std::index_sequence_for()`
3199 template <typename... Ts>
3201
3203
3204#endif
3205
3206// dispatch utility (taken from ranges-v3)
3207 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3208 template<> struct priority_tag<0> {};
3209
3210 // taken from ranges-v3
3211 template<typename T>
3213 {
3214 static JSON_INLINE_VARIABLE constexpr T value{};
3215 };
3216
3217#ifndef JSON_HAS_CPP_17
3218 template<typename T>
3219 constexpr T static_const<T>::value;
3220#endif
3221
3222 template<typename T, typename... Args>
3223 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3224 {
3225 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3226 }
3227
3228} // namespace detail
3230
3231// #include <nlohmann/detail/meta/type_traits.hpp>
3232// __ _____ _____ _____
3233// __| | __| | | | JSON for Modern C++
3234// | | |__ | | | | | | version 3.11.3
3235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3236//
3237// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3238// SPDX-License-Identifier: MIT
3239
3240
3241
3242#include <limits> // numeric_limits
3243#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3244#include <utility> // declval
3245#include <tuple> // tuple
3246#include <string> // char_traits
3247
3248// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3249// __ _____ _____ _____
3250// __| | __| | | | JSON for Modern C++
3251// | | |__ | | | | | | version 3.11.3
3252// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3253//
3254// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3255// SPDX-License-Identifier: MIT
3256
3257
3258
3259#include <iterator> // random_access_iterator_tag
3260
3261// #include <nlohmann/detail/abi_macros.hpp>
3262
3263// #include <nlohmann/detail/meta/void_t.hpp>
3264
3265// #include <nlohmann/detail/meta/cpp_future.hpp>
3266
3267
3269namespace detail
3270{
3271
3272 template<typename It, typename = void>
3274
3275 template<typename It>
3277 It,
3278 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3279 typename It::reference, typename It::iterator_category >>
3280 {
3281 using difference_type = typename It::difference_type;
3282 using value_type = typename It::value_type;
3283 using pointer = typename It::pointer;
3284 using reference = typename It::reference;
3285 using iterator_category = typename It::iterator_category;
3286 };
3287
3288 // This is required as some compilers implement std::iterator_traits in a way that
3289 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3290 template<typename T, typename = void>
3292 {
3293 };
3294
3295 template<typename T>
3296 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3297 : iterator_types<T>
3298 {
3299 };
3300
3301 template<typename T>
3303 {
3304 using iterator_category = std::random_access_iterator_tag;
3305 using value_type = T;
3306 using difference_type = ptrdiff_t;
3307 using pointer = T*;
3308 using reference = T&;
3309 };
3310
3311} // namespace detail
3313
3314// #include <nlohmann/detail/macro_scope.hpp>
3315
3316// #include <nlohmann/detail/meta/call_std/begin.hpp>
3317// __ _____ _____ _____
3318// __| | __| | | | JSON for Modern C++
3319// | | |__ | | | | | | version 3.11.3
3320// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3321//
3322// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3323// SPDX-License-Identifier: MIT
3324
3325
3326
3327// #include <nlohmann/detail/macro_scope.hpp>
3328
3329
3331
3333
3335
3336// #include <nlohmann/detail/meta/call_std/end.hpp>
3337// __ _____ _____ _____
3338// __| | __| | | | JSON for Modern C++
3339// | | |__ | | | | | | version 3.11.3
3340// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3341//
3342// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3343// SPDX-License-Identifier: MIT
3344
3345
3346
3347// #include <nlohmann/detail/macro_scope.hpp>
3348
3349
3351
3353
3355
3356// #include <nlohmann/detail/meta/cpp_future.hpp>
3357
3358// #include <nlohmann/detail/meta/detected.hpp>
3359
3360// #include <nlohmann/json_fwd.hpp>
3361// __ _____ _____ _____
3362// __| | __| | | | JSON for Modern C++
3363// | | |__ | | | | | | version 3.11.3
3364// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3365//
3366// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3367// SPDX-License-Identifier: MIT
3368
3369#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3370#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3371
3372#include <cstdint> // int64_t, uint64_t
3373#include <map> // map
3374#include <memory> // allocator
3375#include <string> // string
3376#include <vector> // vector
3377
3378// #include <nlohmann/detail/abi_macros.hpp>
3379
3380
3387
3395template<typename T = void, typename SFINAE = void>
3396struct adl_serializer;
3397
3400template<template<typename U, typename V, typename... Args> class ObjectType =
3401 std::map,
3402 template<typename U, typename... Args> class ArrayType = std::vector,
3403 class StringType = std::string, class BooleanType = bool,
3404 class NumberIntegerType = std::int64_t,
3405 class NumberUnsignedType = std::uint64_t,
3406 class NumberFloatType = double,
3407 template<typename U> class AllocatorType = std::allocator,
3408 template<typename T, typename SFINAE = void> class JSONSerializer =
3410 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3411 class CustomBaseClass = void>
3412class basic_json;
3413
3416template<typename RefStringType>
3417class json_pointer;
3418
3424
3427template<class Key, class T, class IgnoredLess, class Allocator>
3428struct ordered_map;
3429
3433
3435
3436#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3437
3438
3448namespace detail
3449{
3450
3452 // helpers //
3454
3455 // Note to maintainers:
3456 //
3457 // Every trait in this file expects a non CV-qualified type.
3458 // The only exceptions are in the 'aliases for detected' section
3459 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3460 //
3461 // In this case, T has to be properly CV-qualified to constraint the function arguments
3462 // (e.g. to_json(BasicJsonType&, const T&))
3463
3464 template<typename> struct is_basic_json : std::false_type {};
3465
3467 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3468
3469 // used by exceptions create() member functions
3470 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3471 // false_type otherwise
3472 template<typename BasicJsonContext>
3474 std::integral_constant < bool,
3475 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3476 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3477 {};
3478
3480 // json_ref helpers //
3482
3483 template<typename>
3484 class json_ref;
3485
3486 template<typename>
3487 struct is_json_ref : std::false_type {};
3488
3489 template<typename T>
3490 struct is_json_ref<json_ref<T>> : std::true_type {};
3491
3493 // aliases for detected //
3495
3496 template<typename T>
3497 using mapped_type_t = typename T::mapped_type;
3498
3499 template<typename T>
3500 using key_type_t = typename T::key_type;
3501
3502 template<typename T>
3503 using value_type_t = typename T::value_type;
3504
3505 template<typename T>
3506 using difference_type_t = typename T::difference_type;
3507
3508 template<typename T>
3509 using pointer_t = typename T::pointer;
3510
3511 template<typename T>
3512 using reference_t = typename T::reference;
3513
3514 template<typename T>
3515 using iterator_category_t = typename T::iterator_category;
3516
3517 template<typename T, typename... Args>
3518 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3519
3520 template<typename T, typename... Args>
3521 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3522
3523 template<typename T, typename U>
3524 using get_template_function = decltype(std::declval<T>().template get<U>());
3525
3526 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3527 template<typename BasicJsonType, typename T, typename = void>
3528 struct has_from_json : std::false_type {};
3529
3530 // trait checking if j.get<T> is valid
3531 // use this trait instead of std::is_constructible or std::is_convertible,
3532 // both rely on, or make use of implicit conversions, and thus fail when T
3533 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3534 template <typename BasicJsonType, typename T>
3539
3540 template<typename BasicJsonType, typename T>
3541 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3542 {
3543 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3544
3545 static constexpr bool value =
3547 const BasicJsonType&, T&>::value;
3548 };
3549
3550 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
3551 // this overload is used for non-default-constructible user-defined-types
3552 template<typename BasicJsonType, typename T, typename = void>
3553 struct has_non_default_from_json : std::false_type {};
3554
3555 template<typename BasicJsonType, typename T>
3556 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3557 {
3558 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3559
3560 static constexpr bool value =
3562 const BasicJsonType&>::value;
3563 };
3564
3565 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3566 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3567 template<typename BasicJsonType, typename T, typename = void>
3568 struct has_to_json : std::false_type {};
3569
3570 template<typename BasicJsonType, typename T>
3571 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3572 {
3573 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3574
3575 static constexpr bool value =
3576 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3577 T>::value;
3578 };
3579
3580 template<typename T>
3581 using detect_key_compare = typename T::key_compare;
3582
3583 template<typename T>
3584 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3585
3586 // obtains the actual object key comparator
3587 template<typename BasicJsonType>
3589 {
3590 using object_t = typename BasicJsonType::object_t;
3591 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3592 using type = typename std::conditional < has_key_compare<object_t>::value,
3593 typename object_t::key_compare, object_comparator_t>::type;
3594 };
3595
3596 template<typename BasicJsonType>
3598
3600 // char_traits //
3602
3603 // Primary template of char_traits calls std char_traits
3604 template<typename T>
3605 struct char_traits : std::char_traits<T>
3606 {};
3607
3608 // Explicitly define char traits for unsigned char since it is not standard
3609 template<>
3610 struct char_traits<unsigned char> : std::char_traits<char>
3611 {
3612 using char_type = unsigned char;
3613 using int_type = uint64_t;
3614
3615 // Redefine to_int_type function
3616 static int_type to_int_type(char_type c) noexcept
3617 {
3618 return static_cast<int_type>(c);
3619 }
3620
3622 {
3623 return static_cast<char_type>(i);
3624 }
3625
3626 static constexpr int_type eof() noexcept
3627 {
3628 return static_cast<int_type>(EOF);
3629 }
3630 };
3631
3632 // Explicitly define char traits for signed char since it is not standard
3633 template<>
3634 struct char_traits<signed char> : std::char_traits<char>
3635 {
3636 using char_type = signed char;
3637 using int_type = uint64_t;
3638
3639 // Redefine to_int_type function
3640 static int_type to_int_type(char_type c) noexcept
3641 {
3642 return static_cast<int_type>(c);
3643 }
3644
3646 {
3647 return static_cast<char_type>(i);
3648 }
3649
3650 static constexpr int_type eof() noexcept
3651 {
3652 return static_cast<int_type>(EOF);
3653 }
3654 };
3655
3657 // is_ functions //
3659
3660 // https://en.cppreference.com/w/cpp/types/conjunction
3661 template<class...> struct conjunction : std::true_type { };
3662 template<class B> struct conjunction<B> : B { };
3663 template<class B, class... Bn>
3664 struct conjunction<B, Bn...>
3665 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3666
3667 // https://en.cppreference.com/w/cpp/types/negation
3668 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3669
3670 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3671 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3672 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3673 template <typename T>
3674 struct is_default_constructible : std::is_default_constructible<T> {};
3675
3676 template <typename T1, typename T2>
3677 struct is_default_constructible<std::pair<T1, T2>>
3678 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3679
3680 template <typename T1, typename T2>
3681 struct is_default_constructible<const std::pair<T1, T2>>
3682 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3683
3684 template <typename... Ts>
3685 struct is_default_constructible<std::tuple<Ts...>>
3686 : conjunction<is_default_constructible<Ts>...> {};
3687
3688 template <typename... Ts>
3689 struct is_default_constructible<const std::tuple<Ts...>>
3690 : conjunction<is_default_constructible<Ts>...> {};
3691
3692 template <typename T, typename... Args>
3693 struct is_constructible : std::is_constructible<T, Args...> {};
3694
3695 template <typename T1, typename T2>
3696 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3697
3698 template <typename T1, typename T2>
3699 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3700
3701 template <typename... Ts>
3702 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3703
3704 template <typename... Ts>
3705 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3706
3707 template<typename T, typename = void>
3708 struct is_iterator_traits : std::false_type {};
3709
3710 template<typename T>
3724
3725 template<typename T>
3727 {
3728 private:
3729 using t_ref = typename std::add_lvalue_reference<T>::type;
3730
3731 using iterator = detected_t<result_of_begin, t_ref>;
3732 using sentinel = detected_t<result_of_end, t_ref>;
3733
3734 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3735 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3736 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3737 static constexpr auto is_iterator_begin =
3739
3740 public:
3741 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value&& is_iterator_begin;
3742 };
3743
3744 template<typename R>
3745 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3746
3747 template<typename T>
3749
3750 // The following implementation of is_complete_type is taken from
3751 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3752 // and is written by Xiang Fan who agreed to using it in this library.
3753
3754 template<typename T, typename = void>
3755 struct is_complete_type : std::false_type {};
3756
3757 template<typename T>
3758 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3759
3760 template<typename BasicJsonType, typename CompatibleObjectType,
3761 typename = void>
3762 struct is_compatible_object_type_impl : std::false_type {};
3763
3764 template<typename BasicJsonType, typename CompatibleObjectType>
3766 BasicJsonType, CompatibleObjectType,
3767 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3768 is_detected<key_type_t, CompatibleObjectType>::value >>
3769 {
3770 using object_t = typename BasicJsonType::object_t;
3771
3772 // macOS's is_constructible does not play well with nonesuch...
3773 static constexpr bool value =
3774 is_constructible<typename object_t::key_type,
3775 typename CompatibleObjectType::key_type>::value&&
3776 is_constructible<typename object_t::mapped_type,
3777 typename CompatibleObjectType::mapped_type>::value;
3778 };
3779
3780 template<typename BasicJsonType, typename CompatibleObjectType>
3782 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3783
3784 template<typename BasicJsonType, typename ConstructibleObjectType,
3785 typename = void>
3786 struct is_constructible_object_type_impl : std::false_type {};
3787
3788 template<typename BasicJsonType, typename ConstructibleObjectType>
3790 BasicJsonType, ConstructibleObjectType,
3791 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3792 is_detected<key_type_t, ConstructibleObjectType>::value >>
3793 {
3794 using object_t = typename BasicJsonType::object_t;
3795
3796 static constexpr bool value =
3798 (std::is_move_assignable<ConstructibleObjectType>::value ||
3799 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3800 (is_constructible<typename ConstructibleObjectType::key_type,
3801 typename object_t::key_type>::value &&
3802 std::is_same <
3803 typename object_t::mapped_type,
3804 typename ConstructibleObjectType::mapped_type >::value)) ||
3805 (has_from_json<BasicJsonType,
3806 typename ConstructibleObjectType::mapped_type>::value ||
3808 BasicJsonType,
3809 typename ConstructibleObjectType::mapped_type >::value);
3810 };
3811
3812 template<typename BasicJsonType, typename ConstructibleObjectType>
3814 : is_constructible_object_type_impl<BasicJsonType,
3815 ConstructibleObjectType> {};
3816
3817 template<typename BasicJsonType, typename CompatibleStringType>
3823
3824 template<typename BasicJsonType, typename ConstructibleStringType>
3826 {
3827 // launder type through decltype() to fix compilation failure on ICPC
3828#ifdef __INTEL_COMPILER
3829 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3830#else
3831 using laundered_type = ConstructibleStringType;
3832#endif
3833
3834 static constexpr auto value =
3835 conjunction <
3837 is_detected_exact<typename BasicJsonType::string_t::value_type,
3839 };
3840
3841 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3842 struct is_compatible_array_type_impl : std::false_type {};
3843
3844 template<typename BasicJsonType, typename CompatibleArrayType>
3846 BasicJsonType, CompatibleArrayType,
3847 enable_if_t <
3848 is_detected<iterator_t, CompatibleArrayType>::value&&
3849 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value &&
3850 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3851 // c.f. https://github.com/nlohmann/json/pull/3073
3852 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3853 {
3854 static constexpr bool value =
3855 is_constructible<BasicJsonType,
3857 };
3858
3859 template<typename BasicJsonType, typename CompatibleArrayType>
3861 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3862
3863 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3864 struct is_constructible_array_type_impl : std::false_type {};
3865
3866 template<typename BasicJsonType, typename ConstructibleArrayType>
3868 BasicJsonType, ConstructibleArrayType,
3869 enable_if_t<std::is_same<ConstructibleArrayType,
3870 typename BasicJsonType::value_type>::value >>
3871 : std::true_type {};
3872
3873 template<typename BasicJsonType, typename ConstructibleArrayType>
3875 BasicJsonType, ConstructibleArrayType,
3876 enable_if_t < !std::is_same<ConstructibleArrayType,
3877 typename BasicJsonType::value_type>::value &&
3878 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3879 is_default_constructible<ConstructibleArrayType>::value &&
3880 (std::is_move_assignable<ConstructibleArrayType>::value ||
3881 std::is_copy_assignable<ConstructibleArrayType>::value) &&
3882 is_detected<iterator_t, ConstructibleArrayType>::value&&
3883 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3884 is_detected<range_value_t, ConstructibleArrayType>::value &&
3885 // special case for types like std::filesystem::path whose iterator's value_type are themselves
3886 // c.f. https://github.com/nlohmann/json/pull/3073
3887 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3889 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3890 {
3892
3893 static constexpr bool value =
3894 std::is_same<value_type,
3895 typename BasicJsonType::array_t::value_type>::value ||
3896 has_from_json<BasicJsonType,
3899 BasicJsonType,
3901 };
3902
3903 template<typename BasicJsonType, typename ConstructibleArrayType>
3905 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3906
3907 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3908 typename = void>
3909 struct is_compatible_integer_type_impl : std::false_type {};
3910
3911 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3913 RealIntegerType, CompatibleNumberIntegerType,
3914 enable_if_t < std::is_integral<RealIntegerType>::value&&
3915 std::is_integral<CompatibleNumberIntegerType>::value &&
3916 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3917 {
3918 // is there an assert somewhere on overflows?
3919 using RealLimits = std::numeric_limits<RealIntegerType>;
3920 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3921
3922 static constexpr auto value =
3923 is_constructible<RealIntegerType,
3924 CompatibleNumberIntegerType>::value&&
3925 CompatibleLimits::is_integer&&
3926 RealLimits::is_signed == CompatibleLimits::is_signed;
3927 };
3928
3929 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3931 : is_compatible_integer_type_impl<RealIntegerType,
3932 CompatibleNumberIntegerType> {};
3933
3934 template<typename BasicJsonType, typename CompatibleType, typename = void>
3935 struct is_compatible_type_impl : std::false_type {};
3936
3937 template<typename BasicJsonType, typename CompatibleType>
3939 BasicJsonType, CompatibleType,
3940 enable_if_t<is_complete_type<CompatibleType>::value >>
3941 {
3942 static constexpr bool value =
3944 };
3945
3946 template<typename BasicJsonType, typename CompatibleType>
3948 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3949
3950 template<typename T1, typename T2>
3951 struct is_constructible_tuple : std::false_type {};
3952
3953 template<typename T1, typename... Args>
3954 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3955
3956 template<typename BasicJsonType, typename T>
3957 struct is_json_iterator_of : std::false_type {};
3958
3959 template<typename BasicJsonType>
3960 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3961
3962 template<typename BasicJsonType>
3963 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3964 {};
3965
3966 // checks if a given type T is a template specialization of Primary
3967 template<template <typename...> class Primary, typename T>
3968 struct is_specialization_of : std::false_type {};
3969
3970 template<template <typename...> class Primary, typename... Args>
3971 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3972
3973 template<typename T>
3975
3976 // checks if A and B are comparable using Compare functor
3977 template<typename Compare, typename A, typename B, typename = void>
3978 struct is_comparable : std::false_type {};
3979
3980 template<typename Compare, typename A, typename B>
3981 struct is_comparable<Compare, A, B, void_t<
3982 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3983 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3984 >> : std::true_type {};
3985
3986 template<typename T>
3987 using detect_is_transparent = typename T::is_transparent;
3988
3989 // type trait to check if KeyType can be used as object key (without a BasicJsonType)
3990 // see is_usable_as_basic_json_key_type below
3991 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
3992 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
3993 using is_usable_as_key_type = typename std::conditional <
3995 && !(ExcludeObjectKeyType&& std::is_same<KeyType,
3996 ObjectKeyType>::value)
3997 && (!RequireTransparentComparator
3998 || is_detected <detect_is_transparent, Comparator>::value)
4000 std::true_type,
4001 std::false_type >::type;
4002
4003 // type trait to check if KeyType can be used as object key
4004 // true if:
4005 // - KeyType is comparable with BasicJsonType::object_t::key_type
4006 // - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4007 // - the comparator is transparent or RequireTransparentComparator is false
4008 // - KeyType is not a JSON iterator or json_pointer
4009 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4010 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4011 using is_usable_as_basic_json_key_type = typename std::conditional <
4012 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4013 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4014 RequireTransparentComparator, ExcludeObjectKeyType>::value
4016 std::true_type,
4017 std::false_type >::type;
4018
4019 template<typename ObjectType, typename KeyType>
4020 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4021
4022 // type trait to check if object_t has an erase() member functions accepting KeyType
4023 template<typename BasicJsonType, typename KeyType>
4024 using has_erase_with_key_type = typename std::conditional <
4025 is_detected <
4027 typename BasicJsonType::object_t, KeyType >::value,
4028 std::true_type,
4029 std::false_type >::type;
4030
4031 // a naive helper to check if a type is an ordered_map (exploits the fact that
4032 // ordered_map inherits capacity() from std::vector)
4033 template <typename T>
4035 {
4036 using one = char;
4037
4038 struct two
4039 {
4040 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4041 };
4042
4043 template <typename C> static one test(decltype(&C::capacity));
4044 template <typename C> static two test(...);
4045
4046 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4047 };
4048
4049 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4050 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4052 {
4053 return static_cast<T>(value);
4054 }
4055
4056 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4058 {
4059 return value;
4060 }
4061
4062 template<typename... Types>
4064
4065 template<typename... Types>
4067
4068 template<typename... Types>
4070
4071 // there's a disjunction trait in another PR; replace when merged
4072 template<typename... Types>
4073 using same_sign = std::integral_constant < bool,
4074 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4075
4076 template<typename OfType, typename T>
4077 using never_out_of_range = std::integral_constant < bool,
4078 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4079 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4080
4081 template<typename OfType, typename T,
4082 bool OfTypeSigned = std::is_signed<OfType>::value,
4083 bool TSigned = std::is_signed<T>::value>
4085
4086 template<typename OfType, typename T>
4087 struct value_in_range_of_impl2<OfType, T, false, false>
4088 {
4089 static constexpr bool test(T val)
4090 {
4091 using CommonType = typename std::common_type<OfType, T>::type;
4092 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4093 }
4094 };
4095
4096 template<typename OfType, typename T>
4097 struct value_in_range_of_impl2<OfType, T, true, false>
4098 {
4099 static constexpr bool test(T val)
4100 {
4101 using CommonType = typename std::common_type<OfType, T>::type;
4102 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4103 }
4104 };
4105
4106 template<typename OfType, typename T>
4107 struct value_in_range_of_impl2<OfType, T, false, true>
4108 {
4109 static constexpr bool test(T val)
4110 {
4111 using CommonType = typename std::common_type<OfType, T>::type;
4112 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4113 }
4114 };
4115
4116 template<typename OfType, typename T>
4117 struct value_in_range_of_impl2<OfType, T, true, true>
4118 {
4119 static constexpr bool test(T val)
4120 {
4121 using CommonType = typename std::common_type<OfType, T>::type;
4122 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4123 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4124 }
4125 };
4126
4127 template<typename OfType, typename T,
4128 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4131
4132 template<typename OfType, typename T>
4133 struct value_in_range_of_impl1<OfType, T, false>
4134 {
4135 static constexpr bool test(T val)
4136 {
4138 }
4139 };
4140
4141 template<typename OfType, typename T>
4142 struct value_in_range_of_impl1<OfType, T, true>
4143 {
4144 static constexpr bool test(T /*val*/)
4145 {
4146 return true;
4147 }
4148 };
4149
4150 template<typename OfType, typename T>
4151 inline constexpr bool value_in_range_of(T val)
4152 {
4154 }
4155
4156 template<bool Value>
4157 using bool_constant = std::integral_constant<bool, Value>;
4158
4160 // is_c_string
4162
4163 namespace impl
4164 {
4165
4166 template<typename T>
4167 inline constexpr bool is_c_string()
4168 {
4169 using TUnExt = typename std::remove_extent<T>::type;
4170 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4171 using TUnPtr = typename std::remove_pointer<T>::type;
4172 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4173 return
4174 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4175 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4176 }
4177
4178 } // namespace impl
4179
4180 // checks whether T is a [cv] char */[cv] char[] C string
4181 template<typename T>
4182 struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4183
4184 template<typename T>
4186
4188 // is_transparent
4190
4191 namespace impl
4192 {
4193
4194 template<typename T>
4195 inline constexpr bool is_transparent()
4196 {
4198 }
4199
4200 } // namespace impl
4201
4202 // checks whether T has a member named is_transparent
4203 template<typename T>
4204 struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4205
4207
4208} // namespace detail
4210
4211// #include <nlohmann/detail/string_concat.hpp>
4212// __ _____ _____ _____
4213// __| | __| | | | JSON for Modern C++
4214// | | |__ | | | | | | version 3.11.3
4215// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4216//
4217// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4218// SPDX-License-Identifier: MIT
4219
4220
4221
4222#include <cstring> // strlen
4223#include <string> // string
4224#include <utility> // forward
4225
4226// #include <nlohmann/detail/meta/cpp_future.hpp>
4227
4228// #include <nlohmann/detail/meta/detected.hpp>
4229
4230
4232namespace detail
4233{
4234
4235 inline std::size_t concat_length()
4236 {
4237 return 0;
4238 }
4239
4240 template<typename... Args>
4241 inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4242
4243 template<typename StringType, typename... Args>
4244 inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4245
4246 template<typename... Args>
4247 inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4248 {
4249 return 1 + concat_length(rest...);
4250 }
4251
4252 template<typename... Args>
4253 inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4254 {
4255 // cppcheck-suppress ignoredReturnValue
4256 return ::strlen(cstr) + concat_length(rest...);
4257 }
4258
4259 template<typename StringType, typename... Args>
4260 inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4261 {
4262 return str.size() + concat_length(rest...);
4263 }
4264
4265 template<typename OutStringType>
4266 inline void concat_into(OutStringType& /*out*/)
4267 {}
4268
4269 template<typename StringType, typename Arg>
4270 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg&& >()));
4271
4272 template<typename StringType, typename Arg>
4274
4275 template<typename StringType, typename Arg>
4276 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg&& >());
4277
4278 template<typename StringType, typename Arg>
4280
4281 template<typename StringType, typename Arg>
4282 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4283
4284 template<typename StringType, typename Arg>
4286
4287 template<typename StringType, typename Arg>
4288 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4289
4290 template<typename StringType, typename Arg>
4292
4293 template < typename OutStringType, typename Arg, typename... Args,
4294 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4296 inline void concat_into(OutStringType& out, Arg&& arg, Args && ... rest);
4297
4298 template < typename OutStringType, typename Arg, typename... Args,
4299 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4302 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4303
4304 template < typename OutStringType, typename Arg, typename... Args,
4305 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4309 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4310
4311 template<typename OutStringType, typename Arg, typename... Args,
4313 inline void concat_into(OutStringType& out, Arg&& arg, Args && ... rest)
4314 {
4315 out.append(std::forward<Arg>(arg));
4316 concat_into(out, std::forward<Args>(rest)...);
4317 }
4318
4319 template < typename OutStringType, typename Arg, typename... Args,
4320 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4321 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4322 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4323 {
4324 out += std::forward<Arg>(arg);
4325 concat_into(out, std::forward<Args>(rest)...);
4326 }
4327
4328 template < typename OutStringType, typename Arg, typename... Args,
4329 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4330 && !detect_string_can_append_op<OutStringType, Arg>::value
4331 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4332 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4333 {
4334 out.append(arg.begin(), arg.end());
4335 concat_into(out, std::forward<Args>(rest)...);
4336 }
4337
4338 template < typename OutStringType, typename Arg, typename... Args,
4339 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4340 && !detect_string_can_append_op<OutStringType, Arg>::value
4341 && !detect_string_can_append_iter<OutStringType, Arg>::value
4342 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4343 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4344 {
4345 out.append(arg.data(), arg.size());
4346 concat_into(out, std::forward<Args>(rest)...);
4347 }
4348
4349 template<typename OutStringType = std::string, typename... Args>
4350 inline OutStringType concat(Args && ... args)
4351 {
4352 OutStringType str;
4353 str.reserve(concat_length(args...));
4354 concat_into(str, std::forward<Args>(args)...);
4355 return str;
4356 }
4357
4358} // namespace detail
4360
4361
4363namespace detail
4364{
4365
4367 // exceptions //
4369
4372 class exception : public std::exception
4373 {
4374 public:
4376 const char* what() const noexcept override
4377 {
4378 return m.what();
4379 }
4380
4382 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4383
4384 protected:
4386 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4387
4388 static std::string name(const std::string& ename, int id_)
4389 {
4390 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4391 }
4392
4393 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4394 {
4395 return "";
4396 }
4397
4398 template<typename BasicJsonType>
4399 static std::string diagnostics(const BasicJsonType* leaf_element)
4400 {
4401#if JSON_DIAGNOSTICS
4402 std::vector<std::string> tokens;
4403 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4404 {
4405 switch (current->m_parent->type())
4406 {
4407 case value_t::array:
4408 {
4409 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4410 {
4411 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4412 {
4413 tokens.emplace_back(std::to_string(i));
4414 break;
4415 }
4416 }
4417 break;
4418 }
4419
4420 case value_t::object:
4421 {
4422 for (const auto& element : *current->m_parent->m_data.m_value.object)
4423 {
4424 if (&element.second == current)
4425 {
4426 tokens.emplace_back(element.first.c_str());
4427 break;
4428 }
4429 }
4430 break;
4431 }
4432
4433 case value_t::null: // LCOV_EXCL_LINE
4434 case value_t::string: // LCOV_EXCL_LINE
4435 case value_t::boolean: // LCOV_EXCL_LINE
4436 case value_t::number_integer: // LCOV_EXCL_LINE
4437 case value_t::number_unsigned: // LCOV_EXCL_LINE
4438 case value_t::number_float: // LCOV_EXCL_LINE
4439 case value_t::binary: // LCOV_EXCL_LINE
4440 case value_t::discarded: // LCOV_EXCL_LINE
4441 default: // LCOV_EXCL_LINE
4442 break; // LCOV_EXCL_LINE
4443 }
4444 }
4445
4446 if (tokens.empty())
4447 {
4448 return "";
4449 }
4450
4451 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4452 [](const std::string& a, const std::string& b)
4453 {
4454 return concat(a, '/', detail::escape(b));
4455 });
4456 return concat('(', str, ") ");
4457#else
4458 static_cast<void>(leaf_element);
4459 return "";
4460#endif
4461 }
4462
4463 private:
4465 std::runtime_error m;
4466 };
4467
4470 class parse_error : public exception
4471 {
4472 public:
4482 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4483 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4484 {
4485 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4486 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4487 return { id_, pos.chars_read_total, w.c_str() };
4488 }
4489
4490 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4491 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4492 {
4493 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4494 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4495 ": ", exception::diagnostics(context), what_arg);
4496 return { id_, byte_, w.c_str() };
4497 }
4498
4508 const std::size_t byte;
4509
4510 private:
4511 parse_error(int id_, std::size_t byte_, const char* what_arg)
4512 : exception(id_, what_arg), byte(byte_) {}
4513
4514 static std::string position_string(const position_t& pos)
4515 {
4516 return concat(" at line ", std::to_string(pos.lines_read + 1),
4517 ", column ", std::to_string(pos.chars_read_current_line));
4518 }
4519 };
4520
4524 {
4525 public:
4526 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4527 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4528 {
4529 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4530 return { id_, w.c_str() };
4531 }
4532
4533 private:
4535 invalid_iterator(int id_, const char* what_arg)
4536 : exception(id_, what_arg) {}
4537 };
4538
4541 class type_error : public exception
4542 {
4543 public:
4544 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4545 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4546 {
4547 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4548 return { id_, w.c_str() };
4549 }
4550
4551 private:
4553 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4554 };
4555
4559 {
4560 public:
4561 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4562 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4563 {
4564 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4565 return { id_, w.c_str() };
4566 }
4567
4568 private:
4570 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4571 };
4572
4575 class other_error : public exception
4576 {
4577 public:
4578 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4579 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4580 {
4581 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4582 return { id_, w.c_str() };
4583 }
4584
4585 private:
4587 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4588 };
4589
4590} // namespace detail
4592
4593// #include <nlohmann/detail/macro_scope.hpp>
4594
4595// #include <nlohmann/detail/meta/cpp_future.hpp>
4596
4597// #include <nlohmann/detail/meta/identity_tag.hpp>
4598// __ _____ _____ _____
4599// __| | __| | | | JSON for Modern C++
4600// | | |__ | | | | | | version 3.11.3
4601// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4602//
4603// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4604// SPDX-License-Identifier: MIT
4605
4606
4607
4608// #include <nlohmann/detail/abi_macros.hpp>
4609
4610
4612namespace detail
4613{
4614
4615 // dispatching helper struct
4616 template <class T> struct identity_tag {};
4617
4618} // namespace detail
4620
4621// #include <nlohmann/detail/meta/std_fs.hpp>
4622// __ _____ _____ _____
4623// __| | __| | | | JSON for Modern C++
4624// | | |__ | | | | | | version 3.11.3
4625// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4626//
4627// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4628// SPDX-License-Identifier: MIT
4629
4630
4631
4632// #include <nlohmann/detail/macro_scope.hpp>
4633
4634
4635#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4636#include <experimental/filesystem>
4638namespace detail
4639{
4640 namespace std_fs = std::experimental::filesystem;
4641} // namespace detail
4643#elif JSON_HAS_FILESYSTEM
4644#include <filesystem>
4646namespace detail
4647{
4648 namespace std_fs = std::filesystem;
4649} // namespace detail
4651#endif
4652
4653// #include <nlohmann/detail/meta/type_traits.hpp>
4654
4655// #include <nlohmann/detail/string_concat.hpp>
4656
4657// #include <nlohmann/detail/value_t.hpp>
4658
4659
4661namespace detail
4662{
4663
4664 template<typename BasicJsonType>
4665 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4666 {
4667 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4668 {
4669 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4670 }
4671 n = nullptr;
4672 }
4673
4674 // overloads for basic_json template parameters
4675 template < typename BasicJsonType, typename ArithmeticType,
4676 enable_if_t < std::is_arithmetic<ArithmeticType>::value &&
4677 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4678 int > = 0 >
4679 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4680 {
4681 switch (static_cast<value_t>(j))
4682 {
4684 {
4685 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4686 break;
4687 }
4689 {
4690 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4691 break;
4692 }
4694 {
4695 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4696 break;
4697 }
4698
4699 case value_t::null:
4700 case value_t::object:
4701 case value_t::array:
4702 case value_t::string:
4703 case value_t::boolean:
4704 case value_t::binary:
4705 case value_t::discarded:
4706 default:
4707 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4708 }
4709 }
4710
4711 template<typename BasicJsonType>
4712 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4713 {
4714 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4715 {
4716 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4717 }
4718 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4719 }
4720
4721 template<typename BasicJsonType>
4722 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4723 {
4724 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4725 {
4726 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4727 }
4728 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4729 }
4730
4731 template <
4732 typename BasicJsonType, typename StringType,
4733 enable_if_t <
4734 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4735 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4736 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4737 && !is_json_ref<StringType>::value, int > = 0 >
4738 inline void from_json(const BasicJsonType& j, StringType& s)
4739 {
4740 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4741 {
4742 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4743 }
4744
4745 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4746 }
4747
4748 template<typename BasicJsonType>
4749 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4750 {
4751 get_arithmetic_value(j, val);
4752 }
4753
4754 template<typename BasicJsonType>
4755 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4756 {
4757 get_arithmetic_value(j, val);
4758 }
4759
4760 template<typename BasicJsonType>
4761 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4762 {
4763 get_arithmetic_value(j, val);
4764 }
4765
4766#if !JSON_DISABLE_ENUM_SERIALIZATION
4767 template<typename BasicJsonType, typename EnumType,
4768 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4769 inline void from_json(const BasicJsonType& j, EnumType& e)
4770 {
4771 typename std::underlying_type<EnumType>::type val;
4772 get_arithmetic_value(j, val);
4773 e = static_cast<EnumType>(val);
4774 }
4775#endif // JSON_DISABLE_ENUM_SERIALIZATION
4776
4777 // forward_list doesn't have an insert method
4778 template<typename BasicJsonType, typename T, typename Allocator,
4779 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4780 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4781 {
4782 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4783 {
4784 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4785 }
4786 l.clear();
4787 std::transform(j.rbegin(), j.rend(),
4788 std::front_inserter(l), [](const BasicJsonType& i)
4789 {
4790 return i.template get<T>();
4791 });
4792 }
4793
4794 // valarray doesn't have an insert method
4795 template<typename BasicJsonType, typename T,
4796 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4797 inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4798 {
4799 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4800 {
4801 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4802 }
4803 l.resize(j.size());
4804 std::transform(j.begin(), j.end(), std::begin(l),
4805 [](const BasicJsonType& elem)
4806 {
4807 return elem.template get<T>();
4808 });
4809 }
4810
4811 template<typename BasicJsonType, typename T, std::size_t N>
4812 auto from_json(const BasicJsonType& j, T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4813 -> decltype(j.template get<T>(), void())
4814 {
4815 for (std::size_t i = 0; i < N; ++i)
4816 {
4817 arr[i] = j.at(i).template get<T>();
4818 }
4819 }
4820
4821 template<typename BasicJsonType>
4822 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4823 {
4824 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4825 }
4826
4827 template<typename BasicJsonType, typename T, std::size_t N>
4828 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4829 priority_tag<2> /*unused*/)
4830 -> decltype(j.template get<T>(), void())
4831 {
4832 for (std::size_t i = 0; i < N; ++i)
4833 {
4834 arr[i] = j.at(i).template get<T>();
4835 }
4836 }
4837
4838 template<typename BasicJsonType, typename ConstructibleArrayType,
4840 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4841 int> = 0>
4842 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4843 -> decltype(
4844 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4846 void())
4847 {
4848 using std::end;
4849
4850 ConstructibleArrayType ret;
4851 ret.reserve(j.size());
4852 std::transform(j.begin(), j.end(),
4853 std::inserter(ret, end(ret)), [](const BasicJsonType& i)
4854 {
4855 // get<BasicJsonType>() returns *this, this won't call a from_json
4856 // method when value_type is BasicJsonType
4858 });
4859 arr = std::move(ret);
4860 }
4861
4862 template<typename BasicJsonType, typename ConstructibleArrayType,
4864 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4865 int> = 0>
4866 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4867 priority_tag<0> /*unused*/)
4868 {
4869 using std::end;
4870
4871 ConstructibleArrayType ret;
4872 std::transform(
4873 j.begin(), j.end(), std::inserter(ret, end(ret)),
4874 [](const BasicJsonType& i)
4875 {
4876 // get<BasicJsonType>() returns *this, this won't call a from_json
4877 // method when value_type is BasicJsonType
4879 });
4880 arr = std::move(ret);
4881 }
4882
4883 template < typename BasicJsonType, typename ConstructibleArrayType,
4884 enable_if_t <
4885 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value &&
4886 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value &&
4888 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value &&
4889 !is_basic_json<ConstructibleArrayType>::value,
4890 int > = 0 >
4891 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4892 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4894 void())
4895 {
4896 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4897 {
4898 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4899 }
4900
4901 from_json_array_impl(j, arr, priority_tag<3> {});
4902 }
4903
4904 template < typename BasicJsonType, typename T, std::size_t... Idx >
4905 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4906 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4907 {
4908 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4909 }
4910
4911 template < typename BasicJsonType, typename T, std::size_t N >
4912 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4913 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4914 {
4915 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4916 {
4917 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4918 }
4919
4920 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4921 }
4922
4923 template<typename BasicJsonType>
4924 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4925 {
4926 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4927 {
4928 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4929 }
4930
4931 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4932 }
4933
4934 template<typename BasicJsonType, typename ConstructibleObjectType,
4935 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4936 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4937 {
4938 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4939 {
4940 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4941 }
4942
4943 ConstructibleObjectType ret;
4944 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4945 using value_type = typename ConstructibleObjectType::value_type;
4946 std::transform(
4947 inner_object->begin(), inner_object->end(),
4948 std::inserter(ret, ret.begin()),
4949 [](typename BasicJsonType::object_t::value_type const& p)
4950 {
4951 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4952 });
4953 obj = std::move(ret);
4954 }
4955
4956 // overload for arithmetic types, not chosen for basic_json template arguments
4957 // (BooleanType, etc..); note: Is it really necessary to provide explicit
4958 // overloads for boolean_t etc. in case of a custom BooleanType which is not
4959 // an arithmetic type?
4960 template < typename BasicJsonType, typename ArithmeticType,
4961 enable_if_t <
4962 std::is_arithmetic<ArithmeticType>::value &&
4963 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value &&
4964 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value &&
4965 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value &&
4966 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4967 int > = 0 >
4968 inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4969 {
4970 switch (static_cast<value_t>(j))
4971 {
4973 {
4974 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4975 break;
4976 }
4978 {
4979 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4980 break;
4981 }
4983 {
4984 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4985 break;
4986 }
4987 case value_t::boolean:
4988 {
4989 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
4990 break;
4991 }
4992
4993 case value_t::null:
4994 case value_t::object:
4995 case value_t::array:
4996 case value_t::string:
4997 case value_t::binary:
4998 case value_t::discarded:
4999 default:
5000 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5001 }
5002 }
5003
5004 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5005 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5006 {
5007 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5008 }
5009
5010 template < typename BasicJsonType, class A1, class A2 >
5011 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5012 {
5013 return { std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5014 std::forward<BasicJsonType>(j).at(1).template get<A2>() };
5015 }
5016
5017 template<typename BasicJsonType, typename A1, typename A2>
5018 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5019 {
5020 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5021 }
5022
5023 template<typename BasicJsonType, typename... Args>
5024 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5025 {
5026 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5027 }
5028
5029 template<typename BasicJsonType, typename... Args>
5030 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5031 {
5032 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5033 }
5034
5035 template<typename BasicJsonType, typename TupleRelated>
5036 auto from_json(BasicJsonType&& j, TupleRelated&& t)
5037 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5038 {
5039 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5040 {
5041 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5042 }
5043
5044 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5045 }
5046
5047 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5048 typename = enable_if_t < !std::is_constructible <
5049 typename BasicJsonType::string_t, Key >::value >>
5050 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5051 {
5052 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5053 {
5054 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5055 }
5056 m.clear();
5057 for (const auto& p : j)
5058 {
5059 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5060 {
5061 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5062 }
5063 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5064 }
5065 }
5066
5067 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5068 typename = enable_if_t < !std::is_constructible <
5069 typename BasicJsonType::string_t, Key >::value >>
5070 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5071 {
5072 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5073 {
5074 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5075 }
5076 m.clear();
5077 for (const auto& p : j)
5078 {
5079 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5080 {
5081 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5082 }
5083 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5084 }
5085 }
5086
5087#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5088 template<typename BasicJsonType>
5089 inline void from_json(const BasicJsonType& j, std_fs::path& p)
5090 {
5091 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5092 {
5093 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5094 }
5095 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5096 }
5097#endif
5098
5100 {
5101 template<typename BasicJsonType, typename T>
5102 auto operator()(const BasicJsonType& j, T&& val) const
5103 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5104 -> decltype(from_json(j, std::forward<T>(val)))
5105 {
5106 return from_json(j, std::forward<T>(val));
5107 }
5108 };
5109
5110} // namespace detail
5111
5112#ifndef JSON_HAS_CPP_17
5116namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5117{
5118#endif
5119 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5121#ifndef JSON_HAS_CPP_17
5122} // namespace
5123#endif
5124
5126
5127// #include <nlohmann/detail/conversions/to_json.hpp>
5128// __ _____ _____ _____
5129// __| | __| | | | JSON for Modern C++
5130// | | |__ | | | | | | version 3.11.3
5131// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5132//
5133// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5134// SPDX-License-Identifier: MIT
5135
5136
5137
5138#include <algorithm> // copy
5139#include <iterator> // begin, end
5140#include <string> // string
5141#include <tuple> // tuple, get
5142#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5143#include <utility> // move, forward, declval, pair
5144#include <valarray> // valarray
5145#include <vector> // vector
5146
5147// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5148// __ _____ _____ _____
5149// __| | __| | | | JSON for Modern C++
5150// | | |__ | | | | | | version 3.11.3
5151// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5152//
5153// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5154// SPDX-License-Identifier: MIT
5155
5156
5157
5158#include <cstddef> // size_t
5159#include <iterator> // input_iterator_tag
5160#include <string> // string, to_string
5161#include <tuple> // tuple_size, get, tuple_element
5162#include <utility> // move
5163
5164#if JSON_HAS_RANGES
5165#include <ranges> // enable_borrowed_range
5166#endif
5167
5168// #include <nlohmann/detail/abi_macros.hpp>
5169
5170// #include <nlohmann/detail/meta/type_traits.hpp>
5171
5172// #include <nlohmann/detail/value_t.hpp>
5173
5174
5176namespace detail
5177{
5178
5179 template<typename string_type>
5180 void int_to_string(string_type& target, std::size_t value)
5181 {
5182 // For ADL
5183 using std::to_string;
5184 target = to_string(value);
5185 }
5186 template<typename IteratorType> class iteration_proxy_value
5187 {
5188 public:
5189 using difference_type = std::ptrdiff_t;
5193 using iterator_category = std::input_iterator_tag;
5194 using string_type = typename std::remove_cv< typename std::remove_reference<decltype(std::declval<IteratorType>().key()) >::type >::type;
5195
5196 private:
5198 IteratorType anchor{};
5200 std::size_t array_index = 0;
5202 mutable std::size_t array_index_last = 0;
5204 mutable string_type array_index_str = "0";
5206 string_type empty_str{};
5207
5208 public:
5209 explicit iteration_proxy_value() = default;
5210 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5211 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5212 && std::is_nothrow_default_constructible<string_type>::value)
5213 : anchor(std::move(it))
5214 , array_index(array_index_)
5215 {}
5216
5219 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5221 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5222 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5224 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5225 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5227
5229 const iteration_proxy_value& operator*() const
5230 {
5231 return *this;
5232 }
5233
5236 {
5237 ++anchor;
5238 ++array_index;
5239
5240 return *this;
5241 }
5242
5243 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5244 {
5245 auto tmp = iteration_proxy_value(anchor, array_index);
5246 ++anchor;
5247 ++array_index;
5248 return tmp;
5249 }
5250
5253 {
5254 return anchor == o.anchor;
5255 }
5256
5259 {
5260 return anchor != o.anchor;
5261 }
5262
5264 const string_type& key() const
5265 {
5266 JSON_ASSERT(anchor.m_object != nullptr);
5267
5268 switch (anchor.m_object->type())
5269 {
5270 // use integer array index as key
5271 case value_t::array:
5272 {
5273 if (array_index != array_index_last)
5274 {
5275 int_to_string(array_index_str, array_index);
5276 array_index_last = array_index;
5277 }
5278 return array_index_str;
5279 }
5280
5281 // use key from the object
5282 case value_t::object:
5283 return anchor.key();
5284
5285 // use an empty key for all primitive types
5286 case value_t::null:
5287 case value_t::string:
5288 case value_t::boolean:
5292 case value_t::binary:
5293 case value_t::discarded:
5294 default:
5295 return empty_str;
5296 }
5297 }
5298
5300 typename IteratorType::reference value() const
5301 {
5302 return anchor.value();
5303 }
5304 };
5305
5307 template<typename IteratorType> class iteration_proxy
5308 {
5309 private:
5311 typename IteratorType::pointer container = nullptr;
5312
5313 public:
5314 explicit iteration_proxy() = default;
5315
5317 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5318 : container(&cont) {}
5319
5322 iteration_proxy(iteration_proxy&&) noexcept = default;
5323 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5324 ~iteration_proxy() = default;
5325
5327 iteration_proxy_value<IteratorType> begin() const noexcept
5328 {
5329 return iteration_proxy_value<IteratorType>(container->begin());
5330 }
5331
5334 {
5335 return iteration_proxy_value<IteratorType>(container->end());
5336 }
5337 };
5338
5339 // Structured Bindings Support
5340 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5341 // And see https://github.com/nlohmann/json/pull/1391
5342 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5343 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5344 {
5345 return i.key();
5346 }
5347 // Structured Bindings Support
5348 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
5349 // And see https://github.com/nlohmann/json/pull/1391
5350 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5351 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5352 {
5353 return i.value();
5354 }
5355
5356} // namespace detail
5358
5359// The Addition to the STD Namespace is required to add
5360// Structured Bindings Support to the iteration_proxy_value class
5361// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5362// And see https://github.com/nlohmann/json/pull/1391
5363namespace std
5364{
5365
5366#if defined(__clang__)
5367 // Fix: https://github.com/nlohmann/json/issues/1401
5368#pragma clang diagnostic push
5369#pragma clang diagnostic ignored "-Wmismatched-tags"
5370#endif
5371 template<typename IteratorType>
5372 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5373 : public std::integral_constant<std::size_t, 2> {};
5374
5375 template<std::size_t N, typename IteratorType>
5376 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5377 {
5378 public:
5379 using type = decltype(
5380 get<N>(std::declval <
5381 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5382 };
5383#if defined(__clang__)
5384#pragma clang diagnostic pop
5385#endif
5386
5387} // namespace std
5388
5389#if JSON_HAS_RANGES
5390template <typename IteratorType>
5391inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5392#endif
5393
5394// #include <nlohmann/detail/macro_scope.hpp>
5395
5396// #include <nlohmann/detail/meta/cpp_future.hpp>
5397
5398// #include <nlohmann/detail/meta/std_fs.hpp>
5399
5400// #include <nlohmann/detail/meta/type_traits.hpp>
5401
5402// #include <nlohmann/detail/value_t.hpp>
5403
5404
5406namespace detail
5407{
5408
5410 // constructors //
5412
5413 /*
5414 * Note all external_constructor<>::construct functions need to call
5415 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5416 * allocated value (e.g., a string). See bug issue
5417 * https://github.com/nlohmann/json/issues/2865 for more information.
5418 */
5419
5420 template<value_t> struct external_constructor;
5421
5422 template<>
5424 {
5425 template<typename BasicJsonType>
5426 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5427 {
5428 j.m_data.m_value.destroy(j.m_data.m_type);
5429 j.m_data.m_type = value_t::boolean;
5430 j.m_data.m_value = b;
5431 j.assert_invariant();
5432 }
5433 };
5434
5435 template<>
5437 {
5438 template<typename BasicJsonType>
5439 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5440 {
5441 j.m_data.m_value.destroy(j.m_data.m_type);
5442 j.m_data.m_type = value_t::string;
5443 j.m_data.m_value = s;
5444 j.assert_invariant();
5445 }
5446
5447 template<typename BasicJsonType>
5448 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5449 {
5450 j.m_data.m_value.destroy(j.m_data.m_type);
5451 j.m_data.m_type = value_t::string;
5452 j.m_data.m_value = std::move(s);
5453 j.assert_invariant();
5454 }
5455
5456 template < typename BasicJsonType, typename CompatibleStringType,
5457 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5458 int > = 0 >
5459 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5460 {
5461 j.m_data.m_value.destroy(j.m_data.m_type);
5462 j.m_data.m_type = value_t::string;
5463 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5464 j.assert_invariant();
5465 }
5466 };
5467
5468 template<>
5470 {
5471 template<typename BasicJsonType>
5472 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5473 {
5474 j.m_data.m_value.destroy(j.m_data.m_type);
5475 j.m_data.m_type = value_t::binary;
5476 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5477 j.assert_invariant();
5478 }
5479
5480 template<typename BasicJsonType>
5481 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5482 {
5483 j.m_data.m_value.destroy(j.m_data.m_type);
5484 j.m_data.m_type = value_t::binary;
5485 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5486 j.assert_invariant();
5487 }
5488 };
5489
5490 template<>
5492 {
5493 template<typename BasicJsonType>
5494 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5495 {
5496 j.m_data.m_value.destroy(j.m_data.m_type);
5497 j.m_data.m_type = value_t::number_float;
5498 j.m_data.m_value = val;
5499 j.assert_invariant();
5500 }
5501 };
5502
5503 template<>
5505 {
5506 template<typename BasicJsonType>
5507 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5508 {
5509 j.m_data.m_value.destroy(j.m_data.m_type);
5510 j.m_data.m_type = value_t::number_unsigned;
5511 j.m_data.m_value = val;
5512 j.assert_invariant();
5513 }
5514 };
5515
5516 template<>
5518 {
5519 template<typename BasicJsonType>
5520 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5521 {
5522 j.m_data.m_value.destroy(j.m_data.m_type);
5523 j.m_data.m_type = value_t::number_integer;
5524 j.m_data.m_value = val;
5525 j.assert_invariant();
5526 }
5527 };
5528
5529 template<>
5531 {
5532 template<typename BasicJsonType>
5533 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5534 {
5535 j.m_data.m_value.destroy(j.m_data.m_type);
5536 j.m_data.m_type = value_t::array;
5537 j.m_data.m_value = arr;
5538 j.set_parents();
5539 j.assert_invariant();
5540 }
5541
5542 template<typename BasicJsonType>
5543 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5544 {
5545 j.m_data.m_value.destroy(j.m_data.m_type);
5546 j.m_data.m_type = value_t::array;
5547 j.m_data.m_value = std::move(arr);
5548 j.set_parents();
5549 j.assert_invariant();
5550 }
5551
5552 template < typename BasicJsonType, typename CompatibleArrayType,
5553 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5554 int > = 0 >
5555 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5556 {
5557 using std::begin;
5558 using std::end;
5559
5560 j.m_data.m_value.destroy(j.m_data.m_type);
5561 j.m_data.m_type = value_t::array;
5562 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5563 j.set_parents();
5564 j.assert_invariant();
5565 }
5566
5567 template<typename BasicJsonType>
5568 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5569 {
5570 j.m_data.m_value.destroy(j.m_data.m_type);
5571 j.m_data.m_type = value_t::array;
5572 j.m_data.m_value = value_t::array;
5573 j.m_data.m_value.array->reserve(arr.size());
5574 for (const bool x : arr)
5575 {
5576 j.m_data.m_value.array->push_back(x);
5577 j.set_parent(j.m_data.m_value.array->back());
5578 }
5579 j.assert_invariant();
5580 }
5581
5582 template<typename BasicJsonType, typename T,
5584 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5585 {
5586 j.m_data.m_value.destroy(j.m_data.m_type);
5587 j.m_data.m_type = value_t::array;
5588 j.m_data.m_value = value_t::array;
5589 j.m_data.m_value.array->resize(arr.size());
5590 if (arr.size() > 0)
5591 {
5592 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5593 }
5594 j.set_parents();
5595 j.assert_invariant();
5596 }
5597 };
5598
5599 template<>
5601 {
5602 template<typename BasicJsonType>
5603 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5604 {
5605 j.m_data.m_value.destroy(j.m_data.m_type);
5606 j.m_data.m_type = value_t::object;
5607 j.m_data.m_value = obj;
5608 j.set_parents();
5609 j.assert_invariant();
5610 }
5611
5612 template<typename BasicJsonType>
5613 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5614 {
5615 j.m_data.m_value.destroy(j.m_data.m_type);
5616 j.m_data.m_type = value_t::object;
5617 j.m_data.m_value = std::move(obj);
5618 j.set_parents();
5619 j.assert_invariant();
5620 }
5621
5622 template < typename BasicJsonType, typename CompatibleObjectType,
5623 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5624 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5625 {
5626 using std::begin;
5627 using std::end;
5628
5629 j.m_data.m_value.destroy(j.m_data.m_type);
5630 j.m_data.m_type = value_t::object;
5631 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5632 j.set_parents();
5633 j.assert_invariant();
5634 }
5635 };
5636
5638 // to_json //
5640
5641 template<typename BasicJsonType, typename T,
5642 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5643 inline void to_json(BasicJsonType& j, T b) noexcept
5644 {
5646 }
5647
5648 template < typename BasicJsonType, typename BoolRef,
5649 enable_if_t <
5650 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5651 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5652 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5653 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5654 typename BasicJsonType::boolean_t >::value))
5655 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5656 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5657 {
5658 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5659 }
5660
5661 template<typename BasicJsonType, typename CompatibleString,
5662 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5663 inline void to_json(BasicJsonType& j, const CompatibleString& s)
5664 {
5666 }
5667
5668 template<typename BasicJsonType>
5669 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5670 {
5672 }
5673
5674 template<typename BasicJsonType, typename FloatType,
5675 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5676 inline void to_json(BasicJsonType& j, FloatType val) noexcept
5677 {
5678 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5679 }
5680
5681 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5682 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5683 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5684 {
5685 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5686 }
5687
5688 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5689 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5690 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5691 {
5692 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5693 }
5694
5695#if !JSON_DISABLE_ENUM_SERIALIZATION
5696 template<typename BasicJsonType, typename EnumType,
5697 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5698 inline void to_json(BasicJsonType& j, EnumType e) noexcept
5699 {
5700 using underlying_type = typename std::underlying_type<EnumType>::type;
5701 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5702 }
5703#endif // JSON_DISABLE_ENUM_SERIALIZATION
5704
5705 template<typename BasicJsonType>
5706 inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5707 {
5709 }
5710
5711 template < typename BasicJsonType, typename CompatibleArrayType,
5712 enable_if_t < is_compatible_array_type<BasicJsonType,
5713 CompatibleArrayType>::value &&
5714 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value &&
5716 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value &&
5717 !is_basic_json<CompatibleArrayType>::value,
5718 int > = 0 >
5719 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5720 {
5722 }
5723
5724 template<typename BasicJsonType>
5725 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5726 {
5728 }
5729
5730 template<typename BasicJsonType, typename T,
5731 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5732 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5733 {
5735 }
5736
5737 template<typename BasicJsonType>
5738 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5739 {
5741 }
5742
5743 template < typename BasicJsonType, typename CompatibleObjectType,
5744 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value && !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5745 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5746 {
5748 }
5749
5750 template<typename BasicJsonType>
5751 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5752 {
5754 }
5755
5756 template <
5757 typename BasicJsonType, typename T, std::size_t N,
5758 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5759 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5760 int > = 0 >
5761 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5762 {
5764 }
5765
5766 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5767 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5768 {
5769 j = { p.first, p.second };
5770 }
5771
5772 // for https://github.com/nlohmann/json/pull/1134
5773 template<typename BasicJsonType, typename T,
5775 inline void to_json(BasicJsonType& j, const T& b)
5776 {
5777 j = { {b.key(), b.value()} };
5778 }
5779
5780 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5781 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5782 {
5783 j = { std::get<Idx>(t)... };
5784 }
5785
5786 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5787 inline void to_json(BasicJsonType& j, const T& t)
5788 {
5789 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5790 }
5791
5792#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5793 template<typename BasicJsonType>
5794 inline void to_json(BasicJsonType& j, const std_fs::path& p)
5795 {
5796 j = p.string();
5797 }
5798#endif
5799
5801 {
5802 template<typename BasicJsonType, typename T>
5803 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5804 -> decltype(to_json(j, std::forward<T>(val)), void())
5805 {
5806 return to_json(j, std::forward<T>(val));
5807 }
5808 };
5809} // namespace detail
5810
5811#ifndef JSON_HAS_CPP_17
5815namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5816{
5817#endif
5818 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5820#ifndef JSON_HAS_CPP_17
5821} // namespace
5822#endif
5823
5825
5826// #include <nlohmann/detail/meta/identity_tag.hpp>
5827
5828
5830
5832template<typename ValueType, typename>
5834{
5837 template<typename BasicJsonType, typename TargetType = ValueType>
5838 static auto from_json(BasicJsonType&& j, TargetType& val) noexcept(
5839 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5840 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5841 {
5842 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5843 }
5844
5847 template<typename BasicJsonType, typename TargetType = ValueType>
5848 static auto from_json(BasicJsonType&& j) noexcept(
5849 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5850 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5851 {
5852 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5853 }
5854
5857 template<typename BasicJsonType, typename TargetType = ValueType>
5858 static auto to_json(BasicJsonType& j, TargetType&& val) noexcept(
5859 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5860 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5861 {
5862 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5863 }
5864};
5865
5867
5868// #include <nlohmann/byte_container_with_subtype.hpp>
5869// __ _____ _____ _____
5870// __| | __| | | | JSON for Modern C++
5871// | | |__ | | | | | | version 3.11.3
5872// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5873//
5874// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5875// SPDX-License-Identifier: MIT
5876
5877
5878
5879#include <cstdint> // uint8_t, uint64_t
5880#include <tuple> // tie
5881#include <utility> // move
5882
5883// #include <nlohmann/detail/abi_macros.hpp>
5884
5885
5887
5890template<typename BinaryType>
5891class byte_container_with_subtype : public BinaryType
5892{
5893public:
5894 using container_type = BinaryType;
5895 using subtype_type = std::uint64_t;
5896
5899 : container_type()
5900 {}
5901
5904 : container_type(b)
5905 {}
5906
5908 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5909 : container_type(std::move(b))
5910 {}
5911
5914 : container_type(b)
5915 , m_subtype(subtype_)
5916 , m_has_subtype(true)
5917 {}
5918
5920 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5921 : container_type(std::move(b))
5922 , m_subtype(subtype_)
5923 , m_has_subtype(true)
5924 {}
5925
5927 {
5928 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5929 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5930 }
5931
5933 {
5934 return !(rhs == *this);
5935 }
5936
5939 void set_subtype(subtype_type subtype_) noexcept
5940 {
5941 m_subtype = subtype_;
5942 m_has_subtype = true;
5943 }
5944
5947 constexpr subtype_type subtype() const noexcept
5948 {
5949 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5950 }
5951
5954 constexpr bool has_subtype() const noexcept
5955 {
5956 return m_has_subtype;
5957 }
5958
5961 void clear_subtype() noexcept
5962 {
5963 m_subtype = 0;
5964 m_has_subtype = false;
5965 }
5966
5967private:
5968 subtype_type m_subtype = 0;
5969 bool m_has_subtype = false;
5970};
5971
5973
5974// #include <nlohmann/detail/conversions/from_json.hpp>
5975
5976// #include <nlohmann/detail/conversions/to_json.hpp>
5977
5978// #include <nlohmann/detail/exceptions.hpp>
5979
5980// #include <nlohmann/detail/hash.hpp>
5981// __ _____ _____ _____
5982// __| | __| | | | JSON for Modern C++
5983// | | |__ | | | | | | version 3.11.3
5984// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5985//
5986// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5987// SPDX-License-Identifier: MIT
5988
5989
5990
5991#include <cstdint> // uint8_t
5992#include <cstddef> // size_t
5993#include <functional> // hash
5994
5995// #include <nlohmann/detail/abi_macros.hpp>
5996
5997// #include <nlohmann/detail/value_t.hpp>
5998
5999
6001namespace detail
6002{
6003
6004 // boost::hash_combine
6005 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6006 {
6007 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6008 return seed;
6009 }
6010
6022 template<typename BasicJsonType>
6023 std::size_t hash(const BasicJsonType& j)
6024 {
6025 using string_t = typename BasicJsonType::string_t;
6026 using number_integer_t = typename BasicJsonType::number_integer_t;
6027 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6028 using number_float_t = typename BasicJsonType::number_float_t;
6029
6030 const auto type = static_cast<std::size_t>(j.type());
6031 switch (j.type())
6032 {
6033 case BasicJsonType::value_t::null:
6034 case BasicJsonType::value_t::discarded:
6035 {
6036 return combine(type, 0);
6037 }
6038
6039 case BasicJsonType::value_t::object:
6040 {
6041 auto seed = combine(type, j.size());
6042 for (const auto& element : j.items())
6043 {
6044 const auto h = std::hash<string_t>{}(element.key());
6045 seed = combine(seed, h);
6046 seed = combine(seed, hash(element.value()));
6047 }
6048 return seed;
6049 }
6050
6051 case BasicJsonType::value_t::array:
6052 {
6053 auto seed = combine(type, j.size());
6054 for (const auto& element : j)
6055 {
6056 seed = combine(seed, hash(element));
6057 }
6058 return seed;
6059 }
6060
6061 case BasicJsonType::value_t::string:
6062 {
6063 const auto h = std::hash<string_t>{}(j.template get_ref<const string_t&>());
6064 return combine(type, h);
6065 }
6066
6067 case BasicJsonType::value_t::boolean:
6068 {
6069 const auto h = std::hash<bool>{}(j.template get<bool>());
6070 return combine(type, h);
6071 }
6072
6073 case BasicJsonType::value_t::number_integer:
6074 {
6075 const auto h = std::hash<number_integer_t>{}(j.template get<number_integer_t>());
6076 return combine(type, h);
6077 }
6078
6079 case BasicJsonType::value_t::number_unsigned:
6080 {
6081 const auto h = std::hash<number_unsigned_t>{}(j.template get<number_unsigned_t>());
6082 return combine(type, h);
6083 }
6084
6085 case BasicJsonType::value_t::number_float:
6086 {
6087 const auto h = std::hash<number_float_t>{}(j.template get<number_float_t>());
6088 return combine(type, h);
6089 }
6090
6091 case BasicJsonType::value_t::binary:
6092 {
6093 auto seed = combine(type, j.get_binary().size());
6094 const auto h = std::hash<bool>{}(j.get_binary().has_subtype());
6095 seed = combine(seed, h);
6096 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6097 for (const auto byte : j.get_binary())
6098 {
6099 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6100 }
6101 return seed;
6102 }
6103
6104 default: // LCOV_EXCL_LINE
6105 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6106 return 0; // LCOV_EXCL_LINE
6107 }
6108 }
6109
6110} // namespace detail
6112
6113// #include <nlohmann/detail/input/binary_reader.hpp>
6114// __ _____ _____ _____
6115// __| | __| | | | JSON for Modern C++
6116// | | |__ | | | | | | version 3.11.3
6117// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6118//
6119// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6120// SPDX-License-Identifier: MIT
6121
6122
6123
6124#include <algorithm> // generate_n
6125#include <array> // array
6126#include <cmath> // ldexp
6127#include <cstddef> // size_t
6128#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6129#include <cstdio> // snprintf
6130#include <cstring> // memcpy
6131#include <iterator> // back_inserter
6132#include <limits> // numeric_limits
6133#include <string> // char_traits, string
6134#include <utility> // make_pair, move
6135#include <vector> // vector
6136
6137// #include <nlohmann/detail/exceptions.hpp>
6138
6139// #include <nlohmann/detail/input/input_adapters.hpp>
6140// __ _____ _____ _____
6141// __| | __| | | | JSON for Modern C++
6142// | | |__ | | | | | | version 3.11.3
6143// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6144//
6145// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6146// SPDX-License-Identifier: MIT
6147
6148
6149
6150#include <array> // array
6151#include <cstddef> // size_t
6152#include <cstring> // strlen
6153#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6154#include <memory> // shared_ptr, make_shared, addressof
6155#include <numeric> // accumulate
6156#include <string> // string, char_traits
6157#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6158#include <utility> // pair, declval
6159
6160#ifndef JSON_NO_IO
6161#include <cstdio> // FILE *
6162#include <istream> // istream
6163#endif // JSON_NO_IO
6164
6165// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6166
6167// #include <nlohmann/detail/macro_scope.hpp>
6168
6169// #include <nlohmann/detail/meta/type_traits.hpp>
6170
6171
6173namespace detail
6174{
6175
6178
6180 // input adapters //
6182
6183#ifndef JSON_NO_IO
6189 {
6190 public:
6191 using char_type = char;
6192
6194 explicit file_input_adapter(std::FILE* f) noexcept
6195 : m_file(f)
6196 {
6197 JSON_ASSERT(m_file != nullptr);
6198 }
6199
6200 // make class move-only
6203 file_input_adapter& operator=(const file_input_adapter&) = delete;
6206
6207 std::char_traits<char>::int_type get_character() noexcept
6208 {
6209 return std::fgetc(m_file);
6210 }
6211
6212 private:
6214 std::FILE* m_file;
6215 };
6216
6227 {
6228 public:
6229 using char_type = char;
6230
6232 {
6233 // clear stream flags; we use underlying streambuf I/O, do not
6234 // maintain ifstream flags, except eof
6235 if (is != nullptr)
6236 {
6237 is->clear(is->rdstate() & std::ios::eofbit);
6238 }
6239 }
6240
6241 explicit input_stream_adapter(std::istream& i)
6242 : is(&i), sb(i.rdbuf())
6243 {}
6244
6245 // delete because of pointer members
6249
6251 : is(rhs.is), sb(rhs.sb)
6252 {
6253 rhs.is = nullptr;
6254 rhs.sb = nullptr;
6255 }
6256
6257 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6258 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6259 // end up as the same value, e.g. 0xFFFFFFFF.
6260 std::char_traits<char>::int_type get_character()
6261 {
6262 auto res = sb->sbumpc();
6263 // set eof manually, as we don't use the istream interface.
6264 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6265 {
6266 is->clear(is->rdstate() | std::ios::eofbit);
6267 }
6268 return res;
6269 }
6270
6271 private:
6273 std::istream* is = nullptr;
6274 std::streambuf* sb = nullptr;
6275 };
6276#endif // JSON_NO_IO
6277
6278 // General-purpose iterator-based adapter. It might not be as fast as
6279 // theoretically possible for some containers, but it is extremely versatile.
6280 template<typename IteratorType>
6282 {
6283 public:
6284 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6285
6286 iterator_input_adapter(IteratorType first, IteratorType last)
6287 : current(std::move(first)), end(std::move(last))
6288 {}
6289
6291 {
6292 if (JSON_HEDLEY_LIKELY(current != end))
6293 {
6294 auto result = char_traits<char_type>::to_int_type(*current);
6295 std::advance(current, 1);
6296 return result;
6297 }
6298
6300 }
6301
6302 private:
6303 IteratorType current;
6304 IteratorType end;
6305
6306 template<typename BaseInputAdapter, size_t T>
6308
6309 bool empty() const
6310 {
6311 return current == end;
6312 }
6313 };
6314
6315 template<typename BaseInputAdapter, size_t T>
6317
6318 template<typename BaseInputAdapter>
6319 struct wide_string_input_helper<BaseInputAdapter, 4>
6320 {
6321 // UTF-32
6322 static void fill_buffer(BaseInputAdapter& input,
6323 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6324 size_t& utf8_bytes_index,
6325 size_t& utf8_bytes_filled)
6326 {
6327 utf8_bytes_index = 0;
6328
6329 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6330 {
6331 utf8_bytes[0] = std::char_traits<char>::eof();
6332 utf8_bytes_filled = 1;
6333 }
6334 else
6335 {
6336 // get the current character
6337 const auto wc = input.get_character();
6338
6339 // UTF-32 to UTF-8 encoding
6340 if (wc < 0x80)
6341 {
6342 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6343 utf8_bytes_filled = 1;
6344 }
6345 else if (wc <= 0x7FF)
6346 {
6347 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6348 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6349 utf8_bytes_filled = 2;
6350 }
6351 else if (wc <= 0xFFFF)
6352 {
6353 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6354 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6355 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6356 utf8_bytes_filled = 3;
6357 }
6358 else if (wc <= 0x10FFFF)
6359 {
6360 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6361 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6362 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6363 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6364 utf8_bytes_filled = 4;
6365 }
6366 else
6367 {
6368 // unknown character
6369 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6370 utf8_bytes_filled = 1;
6371 }
6372 }
6373 }
6374 };
6375
6376 template<typename BaseInputAdapter>
6377 struct wide_string_input_helper<BaseInputAdapter, 2>
6378 {
6379 // UTF-16
6380 static void fill_buffer(BaseInputAdapter& input,
6381 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6382 size_t& utf8_bytes_index,
6383 size_t& utf8_bytes_filled)
6384 {
6385 utf8_bytes_index = 0;
6386
6387 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6388 {
6389 utf8_bytes[0] = std::char_traits<char>::eof();
6390 utf8_bytes_filled = 1;
6391 }
6392 else
6393 {
6394 // get the current character
6395 const auto wc = input.get_character();
6396
6397 // UTF-16 to UTF-8 encoding
6398 if (wc < 0x80)
6399 {
6400 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6401 utf8_bytes_filled = 1;
6402 }
6403 else if (wc <= 0x7FF)
6404 {
6405 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6406 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6407 utf8_bytes_filled = 2;
6408 }
6409 else if (0xD800 > wc || wc >= 0xE000)
6410 {
6411 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6412 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6413 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6414 utf8_bytes_filled = 3;
6415 }
6416 else
6417 {
6418 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6419 {
6420 const auto wc2 = static_cast<unsigned int>(input.get_character());
6421 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6422 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6423 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6424 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6425 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6426 utf8_bytes_filled = 4;
6427 }
6428 else
6429 {
6430 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6431 utf8_bytes_filled = 1;
6432 }
6433 }
6434 }
6435 }
6436 };
6437
6438 // Wraps another input adapter to convert wide character types into individual bytes.
6439 template<typename BaseInputAdapter, typename WideCharType>
6441 {
6442 public:
6443 using char_type = char;
6444
6445 wide_string_input_adapter(BaseInputAdapter base)
6446 : base_adapter(base) {}
6447
6448 typename std::char_traits<char>::int_type get_character() noexcept
6449 {
6450 // check if buffer needs to be filled
6451 if (utf8_bytes_index == utf8_bytes_filled)
6452 {
6453 fill_buffer<sizeof(WideCharType)>();
6454
6455 JSON_ASSERT(utf8_bytes_filled > 0);
6456 JSON_ASSERT(utf8_bytes_index == 0);
6457 }
6458
6459 // use buffer
6460 JSON_ASSERT(utf8_bytes_filled > 0);
6461 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6462 return utf8_bytes[utf8_bytes_index++];
6463 }
6464
6465 private:
6466 BaseInputAdapter base_adapter;
6467
6468 template<size_t T>
6469 void fill_buffer()
6470 {
6471 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6472 }
6473
6475 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = { {0, 0, 0, 0} };
6476
6478 std::size_t utf8_bytes_index = 0;
6480 std::size_t utf8_bytes_filled = 0;
6481 };
6482
6483 template<typename IteratorType, typename Enable = void>
6485 {
6486 using iterator_type = IteratorType;
6487 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6489
6490 static adapter_type create(IteratorType first, IteratorType last)
6491 {
6492 return adapter_type(std::move(first), std::move(last));
6493 }
6494 };
6495
6496 template<typename T>
6498 {
6499 using value_type = typename std::iterator_traits<T>::value_type;
6500 enum
6501 {
6502 value = sizeof(value_type) > 1
6503 };
6504 };
6505
6506 template<typename IteratorType>
6508 {
6509 using iterator_type = IteratorType;
6510 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6513
6514 static adapter_type create(IteratorType first, IteratorType last)
6515 {
6516 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6517 }
6518 };
6519
6520 // General purpose iterator-based input
6521 template<typename IteratorType>
6523 {
6525 return factory_type::create(first, last);
6526 }
6527
6528 // Convenience shorthand from container to iterator
6529 // Enables ADL on begin(container) and end(container)
6530 // Encloses the using declarations in namespace for not to leak them to outside scope
6531
6532 namespace container_input_adapter_factory_impl
6533 {
6534
6535 using std::begin;
6536 using std::end;
6537
6538 template<typename ContainerType, typename Enable = void>
6540
6541 template<typename ContainerType>
6542 struct container_input_adapter_factory< ContainerType,
6543 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6544 {
6545 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6546
6547 static adapter_type create(const ContainerType& container)
6548 {
6549 return input_adapter(begin(container), end(container));
6550 }
6551 };
6552
6553 } // namespace container_input_adapter_factory_impl
6554
6555 template<typename ContainerType>
6560
6561#ifndef JSON_NO_IO
6562 // Special cases with fast paths
6563 inline file_input_adapter input_adapter(std::FILE* file)
6564 {
6565 return file_input_adapter(file);
6566 }
6567
6568 inline input_stream_adapter input_adapter(std::istream& stream)
6569 {
6570 return input_stream_adapter(stream);
6571 }
6572
6573 inline input_stream_adapter input_adapter(std::istream&& stream)
6574 {
6575 return input_stream_adapter(stream);
6576 }
6577#endif // JSON_NO_IO
6578
6579 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6580
6581 // Null-delimited strings, and the like.
6582 template < typename CharT,
6583 typename std::enable_if <
6584 std::is_pointer<CharT>::value &&
6585 !std::is_array<CharT>::value&&
6586 std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
6587 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6588 int >::type = 0 >
6590 {
6591 auto length = std::strlen(reinterpret_cast<const char*>(b));
6592 const auto* ptr = reinterpret_cast<const char*>(b);
6593 return input_adapter(ptr, ptr + length);
6594 }
6595
6596 template<typename T, std::size_t N>
6597 auto input_adapter(T(&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6598 {
6599 return input_adapter(array, array + N);
6600 }
6601
6602 // This class only handles inputs of input_buffer_adapter type.
6603 // It's required so that expressions like {ptr, len} can be implicitly cast
6604 // to the correct adapter.
6606 {
6607 public:
6608 template < typename CharT,
6609 typename std::enable_if <
6610 std::is_pointer<CharT>::value&&
6611 std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
6612 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6613 int >::type = 0 >
6614 span_input_adapter(CharT b, std::size_t l)
6615 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6616
6617 template<class IteratorType,
6618 typename std::enable_if<
6619 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6620 int>::type = 0>
6621 span_input_adapter(IteratorType first, IteratorType last)
6622 : ia(input_adapter(first, last)) {}
6623
6625 {
6626 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6627 }
6628
6629 private:
6631 };
6632
6633} // namespace detail
6635
6636// #include <nlohmann/detail/input/json_sax.hpp>
6637// __ _____ _____ _____
6638// __| | __| | | | JSON for Modern C++
6639// | | |__ | | | | | | version 3.11.3
6640// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6641//
6642// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6643// SPDX-License-Identifier: MIT
6644
6645
6646
6647#include <cstddef>
6648#include <string> // string
6649#include <utility> // move
6650#include <vector> // vector
6651
6652// #include <nlohmann/detail/exceptions.hpp>
6653
6654// #include <nlohmann/detail/macro_scope.hpp>
6655
6656// #include <nlohmann/detail/string_concat.hpp>
6657
6658
6660
6669template<typename BasicJsonType>
6671{
6672 using number_integer_t = typename BasicJsonType::number_integer_t;
6673 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6674 using number_float_t = typename BasicJsonType::number_float_t;
6675 using string_t = typename BasicJsonType::string_t;
6676 using binary_t = typename BasicJsonType::binary_t;
6677
6682 virtual bool null() = 0;
6683
6689 virtual bool boolean(bool val) = 0;
6690
6696 virtual bool number_integer(number_integer_t val) = 0;
6697
6703 virtual bool number_unsigned(number_unsigned_t val) = 0;
6704
6711 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6712
6719 virtual bool string(string_t& val) = 0;
6720
6727 virtual bool binary(binary_t& val) = 0;
6728
6735 virtual bool start_object(std::size_t elements) = 0;
6736
6743 virtual bool key(string_t& val) = 0;
6744
6749 virtual bool end_object() = 0;
6750
6757 virtual bool start_array(std::size_t elements) = 0;
6758
6763 virtual bool end_array() = 0;
6764
6772 virtual bool parse_error(std::size_t position,
6773 const std::string& last_token,
6774 const detail::exception& ex) = 0;
6775
6776 json_sax() = default;
6777 json_sax(const json_sax&) = default;
6778 json_sax(json_sax&&) noexcept = default;
6779 json_sax& operator=(const json_sax&) = default;
6780 json_sax& operator=(json_sax&&) noexcept = default;
6781 virtual ~json_sax() = default;
6782};
6783
6784namespace detail
6785{
6799 template<typename BasicJsonType>
6801 {
6802 public:
6803 using number_integer_t = typename BasicJsonType::number_integer_t;
6804 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6805 using number_float_t = typename BasicJsonType::number_float_t;
6806 using string_t = typename BasicJsonType::string_t;
6807 using binary_t = typename BasicJsonType::binary_t;
6808
6814 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6815 : root(r), allow_exceptions(allow_exceptions_)
6816 {}
6817
6818 // make class move-only
6820 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6822 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6824
6825 bool null()
6826 {
6827 handle_value(nullptr);
6828 return true;
6829 }
6830
6831 bool boolean(bool val)
6832 {
6833 handle_value(val);
6834 return true;
6835 }
6836
6838 {
6839 handle_value(val);
6840 return true;
6841 }
6842
6844 {
6845 handle_value(val);
6846 return true;
6847 }
6848
6849 bool number_float(number_float_t val, const string_t& /*unused*/)
6850 {
6851 handle_value(val);
6852 return true;
6853 }
6854
6855 bool string(string_t& val)
6856 {
6857 handle_value(val);
6858 return true;
6859 }
6860
6861 bool binary(binary_t& val)
6862 {
6863 handle_value(std::move(val));
6864 return true;
6865 }
6866
6867 bool start_object(std::size_t len)
6868 {
6869 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6870
6871 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6872 {
6873 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6874 }
6875
6876 return true;
6877 }
6878
6879 bool key(string_t& val)
6880 {
6881 JSON_ASSERT(!ref_stack.empty());
6882 JSON_ASSERT(ref_stack.back()->is_object());
6883
6884 // add null at given key and store the reference for later
6885 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6886 return true;
6887 }
6888
6890 {
6891 JSON_ASSERT(!ref_stack.empty());
6892 JSON_ASSERT(ref_stack.back()->is_object());
6893
6894 ref_stack.back()->set_parents();
6895 ref_stack.pop_back();
6896 return true;
6897 }
6898
6899 bool start_array(std::size_t len)
6900 {
6901 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6902
6903 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6904 {
6905 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6906 }
6907
6908 return true;
6909 }
6910
6912 {
6913 JSON_ASSERT(!ref_stack.empty());
6914 JSON_ASSERT(ref_stack.back()->is_array());
6915
6916 ref_stack.back()->set_parents();
6917 ref_stack.pop_back();
6918 return true;
6919 }
6920
6921 template<class Exception>
6922 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6923 const Exception& ex)
6924 {
6925 errored = true;
6926 static_cast<void>(ex);
6927 if (allow_exceptions)
6928 {
6929 JSON_THROW(ex);
6930 }
6931 return false;
6932 }
6933
6934 constexpr bool is_errored() const
6935 {
6936 return errored;
6937 }
6938
6939 private:
6946 template<typename Value>
6948 BasicJsonType* handle_value(Value&& v)
6949 {
6950 if (ref_stack.empty())
6951 {
6952 root = BasicJsonType(std::forward<Value>(v));
6953 return &root;
6954 }
6955
6956 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6957
6958 if (ref_stack.back()->is_array())
6959 {
6960 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6961 return &(ref_stack.back()->m_data.m_value.array->back());
6962 }
6963
6964 JSON_ASSERT(ref_stack.back()->is_object());
6965 JSON_ASSERT(object_element);
6966 *object_element = BasicJsonType(std::forward<Value>(v));
6967 return object_element;
6968 }
6969
6971 BasicJsonType& root;
6973 std::vector<BasicJsonType*> ref_stack{};
6975 BasicJsonType* object_element = nullptr;
6977 bool errored = false;
6979 const bool allow_exceptions = true;
6980 };
6981
6982 template<typename BasicJsonType>
6984 {
6985 public:
6986 using number_integer_t = typename BasicJsonType::number_integer_t;
6987 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6988 using number_float_t = typename BasicJsonType::number_float_t;
6989 using string_t = typename BasicJsonType::string_t;
6990 using binary_t = typename BasicJsonType::binary_t;
6991 using parser_callback_t = typename BasicJsonType::parser_callback_t;
6992 using parse_event_t = typename BasicJsonType::parse_event_t;
6993
6995 const parser_callback_t cb,
6996 const bool allow_exceptions_ = true)
6997 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
6998 {
6999 keep_stack.push_back(true);
7000 }
7001
7002 // make class move-only
7004 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7006 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7008
7009 bool null()
7010 {
7011 handle_value(nullptr);
7012 return true;
7013 }
7014
7015 bool boolean(bool val)
7016 {
7017 handle_value(val);
7018 return true;
7019 }
7020
7022 {
7023 handle_value(val);
7024 return true;
7025 }
7026
7028 {
7029 handle_value(val);
7030 return true;
7031 }
7032
7033 bool number_float(number_float_t val, const string_t& /*unused*/)
7034 {
7035 handle_value(val);
7036 return true;
7037 }
7038
7039 bool string(string_t& val)
7040 {
7041 handle_value(val);
7042 return true;
7043 }
7044
7045 bool binary(binary_t& val)
7046 {
7047 handle_value(std::move(val));
7048 return true;
7049 }
7050
7051 bool start_object(std::size_t len)
7052 {
7053 // check callback for object start
7054 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7055 keep_stack.push_back(keep);
7056
7057 auto val = handle_value(BasicJsonType::value_t::object, true);
7058 ref_stack.push_back(val.second);
7059
7060 // check object limit
7061 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7062 {
7063 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7064 }
7065
7066 return true;
7067 }
7068
7069 bool key(string_t& val)
7070 {
7071 BasicJsonType k = BasicJsonType(val);
7072
7073 // check callback for key
7074 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7075 key_keep_stack.push_back(keep);
7076
7077 // add discarded value at given key and store the reference for later
7078 if (keep && ref_stack.back())
7079 {
7080 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7081 }
7082
7083 return true;
7084 }
7085
7087 {
7088 if (ref_stack.back())
7089 {
7090 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7091 {
7092 // discard object
7093 *ref_stack.back() = discarded;
7094 }
7095 else
7096 {
7097 ref_stack.back()->set_parents();
7098 }
7099 }
7100
7101 JSON_ASSERT(!ref_stack.empty());
7102 JSON_ASSERT(!keep_stack.empty());
7103 ref_stack.pop_back();
7104 keep_stack.pop_back();
7105
7106 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7107 {
7108 // remove discarded value
7109 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7110 {
7111 if (it->is_discarded())
7112 {
7113 ref_stack.back()->erase(it);
7114 break;
7115 }
7116 }
7117 }
7118
7119 return true;
7120 }
7121
7122 bool start_array(std::size_t len)
7123 {
7124 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7125 keep_stack.push_back(keep);
7126
7127 auto val = handle_value(BasicJsonType::value_t::array, true);
7128 ref_stack.push_back(val.second);
7129
7130 // check array limit
7131 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7132 {
7133 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7134 }
7135
7136 return true;
7137 }
7138
7140 {
7141 bool keep = true;
7142
7143 if (ref_stack.back())
7144 {
7145 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7146 if (keep)
7147 {
7148 ref_stack.back()->set_parents();
7149 }
7150 else
7151 {
7152 // discard array
7153 *ref_stack.back() = discarded;
7154 }
7155 }
7156
7157 JSON_ASSERT(!ref_stack.empty());
7158 JSON_ASSERT(!keep_stack.empty());
7159 ref_stack.pop_back();
7160 keep_stack.pop_back();
7161
7162 // remove discarded value
7163 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7164 {
7165 ref_stack.back()->m_data.m_value.array->pop_back();
7166 }
7167
7168 return true;
7169 }
7170
7171 template<class Exception>
7172 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7173 const Exception& ex)
7174 {
7175 errored = true;
7176 static_cast<void>(ex);
7177 if (allow_exceptions)
7178 {
7179 JSON_THROW(ex);
7180 }
7181 return false;
7182 }
7183
7184 constexpr bool is_errored() const
7185 {
7186 return errored;
7187 }
7188
7189 private:
7205 template<typename Value>
7206 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7207 {
7208 JSON_ASSERT(!keep_stack.empty());
7209
7210 // do not handle this value if we know it would be added to a discarded
7211 // container
7212 if (!keep_stack.back())
7213 {
7214 return { false, nullptr };
7215 }
7216
7217 // create value
7218 auto value = BasicJsonType(std::forward<Value>(v));
7219
7220 // check callback
7221 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7222
7223 // do not handle this value if we just learnt it shall be discarded
7224 if (!keep)
7225 {
7226 return { false, nullptr };
7227 }
7228
7229 if (ref_stack.empty())
7230 {
7231 root = std::move(value);
7232 return { true, &root };
7233 }
7234
7235 // skip this value if we already decided to skip the parent
7236 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7237 if (!ref_stack.back())
7238 {
7239 return { false, nullptr };
7240 }
7241
7242 // we now only expect arrays and objects
7243 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7244
7245 // array
7246 if (ref_stack.back()->is_array())
7247 {
7248 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7249 return { true, &(ref_stack.back()->m_data.m_value.array->back()) };
7250 }
7251
7252 // object
7253 JSON_ASSERT(ref_stack.back()->is_object());
7254 // check if we should store an element for the current key
7255 JSON_ASSERT(!key_keep_stack.empty());
7256 const bool store_element = key_keep_stack.back();
7257 key_keep_stack.pop_back();
7258
7259 if (!store_element)
7260 {
7261 return { false, nullptr };
7262 }
7263
7264 JSON_ASSERT(object_element);
7265 *object_element = std::move(value);
7266 return { true, object_element };
7267 }
7268
7270 BasicJsonType& root;
7272 std::vector<BasicJsonType*> ref_stack{};
7274 std::vector<bool> keep_stack{};
7276 std::vector<bool> key_keep_stack{};
7278 BasicJsonType* object_element = nullptr;
7280 bool errored = false;
7282 const parser_callback_t callback = nullptr;
7284 const bool allow_exceptions = true;
7286 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7287 };
7288
7289 template<typename BasicJsonType>
7291 {
7292 public:
7293 using number_integer_t = typename BasicJsonType::number_integer_t;
7294 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7295 using number_float_t = typename BasicJsonType::number_float_t;
7296 using string_t = typename BasicJsonType::string_t;
7297 using binary_t = typename BasicJsonType::binary_t;
7298
7299 bool null()
7300 {
7301 return true;
7302 }
7303
7304 bool boolean(bool /*unused*/)
7305 {
7306 return true;
7307 }
7308
7310 {
7311 return true;
7312 }
7313
7315 {
7316 return true;
7317 }
7318
7319 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7320 {
7321 return true;
7322 }
7323
7324 bool string(string_t& /*unused*/)
7325 {
7326 return true;
7327 }
7328
7329 bool binary(binary_t& /*unused*/)
7330 {
7331 return true;
7332 }
7333
7334 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7335 {
7336 return true;
7337 }
7338
7339 bool key(string_t& /*unused*/)
7340 {
7341 return true;
7342 }
7343
7345 {
7346 return true;
7347 }
7348
7349 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7350 {
7351 return true;
7352 }
7353
7355 {
7356 return true;
7357 }
7358
7359 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7360 {
7361 return false;
7362 }
7363 };
7364
7365} // namespace detail
7367
7368// #include <nlohmann/detail/input/lexer.hpp>
7369// __ _____ _____ _____
7370// __| | __| | | | JSON for Modern C++
7371// | | |__ | | | | | | version 3.11.3
7372// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7373//
7374// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7375// SPDX-License-Identifier: MIT
7376
7377
7378
7379#include <array> // array
7380#include <clocale> // localeconv
7381#include <cstddef> // size_t
7382#include <cstdio> // snprintf
7383#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7384#include <initializer_list> // initializer_list
7385#include <string> // char_traits, string
7386#include <utility> // move
7387#include <vector> // vector
7388
7389// #include <nlohmann/detail/input/input_adapters.hpp>
7390
7391// #include <nlohmann/detail/input/position_t.hpp>
7392
7393// #include <nlohmann/detail/macro_scope.hpp>
7394
7395// #include <nlohmann/detail/meta/type_traits.hpp>
7396
7397
7399namespace detail
7400{
7401
7403 // lexer //
7405
7406 template<typename BasicJsonType>
7408 {
7409 public:
7411 enum class token_type
7412 {
7413 uninitialized,
7414 literal_true,
7415 literal_false,
7416 literal_null,
7417 value_string,
7418 value_unsigned,
7419 value_integer,
7420 value_float,
7421 begin_array,
7422 begin_object,
7423 end_array,
7424 end_object,
7425 name_separator,
7426 value_separator,
7427 parse_error,
7428 end_of_input,
7429 literal_or_value
7430 };
7431
7435 static const char* token_type_name(const token_type t) noexcept
7436 {
7437 switch (t)
7438 {
7439 case token_type::uninitialized:
7440 return "<uninitialized>";
7441 case token_type::literal_true:
7442 return "true literal";
7443 case token_type::literal_false:
7444 return "false literal";
7445 case token_type::literal_null:
7446 return "null literal";
7447 case token_type::value_string:
7448 return "string literal";
7449 case token_type::value_unsigned:
7450 case token_type::value_integer:
7451 case token_type::value_float:
7452 return "number literal";
7453 case token_type::begin_array:
7454 return "'['";
7455 case token_type::begin_object:
7456 return "'{'";
7457 case token_type::end_array:
7458 return "']'";
7459 case token_type::end_object:
7460 return "'}'";
7461 case token_type::name_separator:
7462 return "':'";
7463 case token_type::value_separator:
7464 return "','";
7465 case token_type::parse_error:
7466 return "<parse error>";
7467 case token_type::end_of_input:
7468 return "end of input";
7469 case token_type::literal_or_value:
7470 return "'[', '{', or a literal";
7471 // LCOV_EXCL_START
7472 default: // catch non-enum values
7473 return "unknown token";
7474 // LCOV_EXCL_STOP
7475 }
7476 }
7477 };
7483 template<typename BasicJsonType, typename InputAdapterType>
7484 class lexer : public lexer_base<BasicJsonType>
7485 {
7486 using number_integer_t = typename BasicJsonType::number_integer_t;
7487 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7488 using number_float_t = typename BasicJsonType::number_float_t;
7489 using string_t = typename BasicJsonType::string_t;
7490 using char_type = typename InputAdapterType::char_type;
7491 using char_int_type = typename char_traits<char_type>::int_type;
7492
7493 public:
7495
7496 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7497 : ia(std::move(adapter))
7498 , ignore_comments(ignore_comments_)
7499 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7500 {}
7501
7502 // delete because of pointer members
7503 lexer(const lexer&) = delete;
7504 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7505 lexer& operator=(lexer&) = delete;
7506 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7507 ~lexer() = default;
7508
7509 private:
7511 // locales
7513
7516 static char get_decimal_point() noexcept
7517 {
7518 const auto* loc = localeconv();
7519 JSON_ASSERT(loc != nullptr);
7520 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7521 }
7522
7524 // scan functions
7526
7542 int get_codepoint()
7543 {
7544 // this function only makes sense after reading `\u`
7545 JSON_ASSERT(current == 'u');
7546 int codepoint = 0;
7547
7548 const auto factors = { 12u, 8u, 4u, 0u };
7549 for (const auto factor : factors)
7550 {
7551 get();
7552
7553 if (current >= '0' && current <= '9')
7554 {
7555 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7556 }
7557 else if (current >= 'A' && current <= 'F')
7558 {
7559 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7560 }
7561 else if (current >= 'a' && current <= 'f')
7562 {
7563 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7564 }
7565 else
7566 {
7567 return -1;
7568 }
7569 }
7570
7571 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7572 return codepoint;
7573 }
7574
7590 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7591 {
7592 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7593 add(current);
7594
7595 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7596 {
7597 get();
7598 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7599 {
7600 add(current);
7601 }
7602 else
7603 {
7604 error_message = "invalid string: ill-formed UTF-8 byte";
7605 return false;
7606 }
7607 }
7608
7609 return true;
7610 }
7611
7627 token_type scan_string()
7628 {
7629 // reset token_buffer (ignore opening quote)
7630 reset();
7631
7632 // we entered the function by reading an open quote
7633 JSON_ASSERT(current == '\"');
7634
7635 while (true)
7636 {
7637 // get next character
7638 switch (get())
7639 {
7640 // end of file while parsing string
7641 case char_traits<char_type>::eof():
7642 {
7643 error_message = "invalid string: missing closing quote";
7644 return token_type::parse_error;
7645 }
7646
7647 // closing quote
7648 case '\"':
7649 {
7650 return token_type::value_string;
7651 }
7652
7653 // escapes
7654 case '\\':
7655 {
7656 switch (get())
7657 {
7658 // quotation mark
7659 case '\"':
7660 add('\"');
7661 break;
7662 // reverse solidus
7663 case '\\':
7664 add('\\');
7665 break;
7666 // solidus
7667 case '/':
7668 add('/');
7669 break;
7670 // backspace
7671 case 'b':
7672 add('\b');
7673 break;
7674 // form feed
7675 case 'f':
7676 add('\f');
7677 break;
7678 // line feed
7679 case 'n':
7680 add('\n');
7681 break;
7682 // carriage return
7683 case 'r':
7684 add('\r');
7685 break;
7686 // tab
7687 case 't':
7688 add('\t');
7689 break;
7690
7691 // unicode escapes
7692 case 'u':
7693 {
7694 const int codepoint1 = get_codepoint();
7695 int codepoint = codepoint1; // start with codepoint1
7696
7697 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7698 {
7699 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7700 return token_type::parse_error;
7701 }
7702
7703 // check if code point is a high surrogate
7704 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7705 {
7706 // expect next \uxxxx entry
7707 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7708 {
7709 const int codepoint2 = get_codepoint();
7710
7711 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7712 {
7713 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7714 return token_type::parse_error;
7715 }
7716
7717 // check if codepoint2 is a low surrogate
7718 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7719 {
7720 // overwrite codepoint
7721 codepoint = static_cast<int>(
7722 // high surrogate occupies the most significant 22 bits
7723 (static_cast<unsigned int>(codepoint1) << 10u)
7724 // low surrogate occupies the least significant 15 bits
7725 + static_cast<unsigned int>(codepoint2)
7726 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7727 // in the result, so we have to subtract with:
7728 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7729 -0x35FDC00u);
7730 }
7731 else
7732 {
7733 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7734 return token_type::parse_error;
7735 }
7736 }
7737 else
7738 {
7739 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7740 return token_type::parse_error;
7741 }
7742 }
7743 else
7744 {
7745 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7746 {
7747 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7748 return token_type::parse_error;
7749 }
7750 }
7751
7752 // result of the above calculation yields a proper codepoint
7753 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7754
7755 // translate codepoint into bytes
7756 if (codepoint < 0x80)
7757 {
7758 // 1-byte characters: 0xxxxxxx (ASCII)
7759 add(static_cast<char_int_type>(codepoint));
7760 }
7761 else if (codepoint <= 0x7FF)
7762 {
7763 // 2-byte characters: 110xxxxx 10xxxxxx
7764 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7765 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7766 }
7767 else if (codepoint <= 0xFFFF)
7768 {
7769 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7770 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7771 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7772 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7773 }
7774 else
7775 {
7776 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7777 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7778 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7779 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7780 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7781 }
7782
7783 break;
7784 }
7785
7786 // other characters after escape
7787 default:
7788 error_message = "invalid string: forbidden character after backslash";
7789 return token_type::parse_error;
7790 }
7791
7792 break;
7793 }
7794
7795 // invalid control characters
7796 case 0x00:
7797 {
7798 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7799 return token_type::parse_error;
7800 }
7801
7802 case 0x01:
7803 {
7804 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7805 return token_type::parse_error;
7806 }
7807
7808 case 0x02:
7809 {
7810 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7811 return token_type::parse_error;
7812 }
7813
7814 case 0x03:
7815 {
7816 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7817 return token_type::parse_error;
7818 }
7819
7820 case 0x04:
7821 {
7822 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7823 return token_type::parse_error;
7824 }
7825
7826 case 0x05:
7827 {
7828 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7829 return token_type::parse_error;
7830 }
7831
7832 case 0x06:
7833 {
7834 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7835 return token_type::parse_error;
7836 }
7837
7838 case 0x07:
7839 {
7840 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7841 return token_type::parse_error;
7842 }
7843
7844 case 0x08:
7845 {
7846 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7847 return token_type::parse_error;
7848 }
7849
7850 case 0x09:
7851 {
7852 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7853 return token_type::parse_error;
7854 }
7855
7856 case 0x0A:
7857 {
7858 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7859 return token_type::parse_error;
7860 }
7861
7862 case 0x0B:
7863 {
7864 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7865 return token_type::parse_error;
7866 }
7867
7868 case 0x0C:
7869 {
7870 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7871 return token_type::parse_error;
7872 }
7873
7874 case 0x0D:
7875 {
7876 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7877 return token_type::parse_error;
7878 }
7879
7880 case 0x0E:
7881 {
7882 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7883 return token_type::parse_error;
7884 }
7885
7886 case 0x0F:
7887 {
7888 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7889 return token_type::parse_error;
7890 }
7891
7892 case 0x10:
7893 {
7894 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7895 return token_type::parse_error;
7896 }
7897
7898 case 0x11:
7899 {
7900 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7901 return token_type::parse_error;
7902 }
7903
7904 case 0x12:
7905 {
7906 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7907 return token_type::parse_error;
7908 }
7909
7910 case 0x13:
7911 {
7912 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7913 return token_type::parse_error;
7914 }
7915
7916 case 0x14:
7917 {
7918 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7919 return token_type::parse_error;
7920 }
7921
7922 case 0x15:
7923 {
7924 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7925 return token_type::parse_error;
7926 }
7927
7928 case 0x16:
7929 {
7930 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7931 return token_type::parse_error;
7932 }
7933
7934 case 0x17:
7935 {
7936 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7937 return token_type::parse_error;
7938 }
7939
7940 case 0x18:
7941 {
7942 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7943 return token_type::parse_error;
7944 }
7945
7946 case 0x19:
7947 {
7948 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7949 return token_type::parse_error;
7950 }
7951
7952 case 0x1A:
7953 {
7954 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7955 return token_type::parse_error;
7956 }
7957
7958 case 0x1B:
7959 {
7960 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7961 return token_type::parse_error;
7962 }
7963
7964 case 0x1C:
7965 {
7966 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7967 return token_type::parse_error;
7968 }
7969
7970 case 0x1D:
7971 {
7972 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7973 return token_type::parse_error;
7974 }
7975
7976 case 0x1E:
7977 {
7978 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7979 return token_type::parse_error;
7980 }
7981
7982 case 0x1F:
7983 {
7984 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7985 return token_type::parse_error;
7986 }
7987
7988 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7989 case 0x20:
7990 case 0x21:
7991 case 0x23:
7992 case 0x24:
7993 case 0x25:
7994 case 0x26:
7995 case 0x27:
7996 case 0x28:
7997 case 0x29:
7998 case 0x2A:
7999 case 0x2B:
8000 case 0x2C:
8001 case 0x2D:
8002 case 0x2E:
8003 case 0x2F:
8004 case 0x30:
8005 case 0x31:
8006 case 0x32:
8007 case 0x33:
8008 case 0x34:
8009 case 0x35:
8010 case 0x36:
8011 case 0x37:
8012 case 0x38:
8013 case 0x39:
8014 case 0x3A:
8015 case 0x3B:
8016 case 0x3C:
8017 case 0x3D:
8018 case 0x3E:
8019 case 0x3F:
8020 case 0x40:
8021 case 0x41:
8022 case 0x42:
8023 case 0x43:
8024 case 0x44:
8025 case 0x45:
8026 case 0x46:
8027 case 0x47:
8028 case 0x48:
8029 case 0x49:
8030 case 0x4A:
8031 case 0x4B:
8032 case 0x4C:
8033 case 0x4D:
8034 case 0x4E:
8035 case 0x4F:
8036 case 0x50:
8037 case 0x51:
8038 case 0x52:
8039 case 0x53:
8040 case 0x54:
8041 case 0x55:
8042 case 0x56:
8043 case 0x57:
8044 case 0x58:
8045 case 0x59:
8046 case 0x5A:
8047 case 0x5B:
8048 case 0x5D:
8049 case 0x5E:
8050 case 0x5F:
8051 case 0x60:
8052 case 0x61:
8053 case 0x62:
8054 case 0x63:
8055 case 0x64:
8056 case 0x65:
8057 case 0x66:
8058 case 0x67:
8059 case 0x68:
8060 case 0x69:
8061 case 0x6A:
8062 case 0x6B:
8063 case 0x6C:
8064 case 0x6D:
8065 case 0x6E:
8066 case 0x6F:
8067 case 0x70:
8068 case 0x71:
8069 case 0x72:
8070 case 0x73:
8071 case 0x74:
8072 case 0x75:
8073 case 0x76:
8074 case 0x77:
8075 case 0x78:
8076 case 0x79:
8077 case 0x7A:
8078 case 0x7B:
8079 case 0x7C:
8080 case 0x7D:
8081 case 0x7E:
8082 case 0x7F:
8083 {
8084 add(current);
8085 break;
8086 }
8087
8088 // U+0080..U+07FF: bytes C2..DF 80..BF
8089 case 0xC2:
8090 case 0xC3:
8091 case 0xC4:
8092 case 0xC5:
8093 case 0xC6:
8094 case 0xC7:
8095 case 0xC8:
8096 case 0xC9:
8097 case 0xCA:
8098 case 0xCB:
8099 case 0xCC:
8100 case 0xCD:
8101 case 0xCE:
8102 case 0xCF:
8103 case 0xD0:
8104 case 0xD1:
8105 case 0xD2:
8106 case 0xD3:
8107 case 0xD4:
8108 case 0xD5:
8109 case 0xD6:
8110 case 0xD7:
8111 case 0xD8:
8112 case 0xD9:
8113 case 0xDA:
8114 case 0xDB:
8115 case 0xDC:
8116 case 0xDD:
8117 case 0xDE:
8118 case 0xDF:
8119 {
8120 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({ 0x80, 0xBF })))
8121 {
8122 return token_type::parse_error;
8123 }
8124 break;
8125 }
8126
8127 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8128 case 0xE0:
8129 {
8130 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0xA0, 0xBF, 0x80, 0xBF }))))
8131 {
8132 return token_type::parse_error;
8133 }
8134 break;
8135 }
8136
8137 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8138 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8139 case 0xE1:
8140 case 0xE2:
8141 case 0xE3:
8142 case 0xE4:
8143 case 0xE5:
8144 case 0xE6:
8145 case 0xE7:
8146 case 0xE8:
8147 case 0xE9:
8148 case 0xEA:
8149 case 0xEB:
8150 case 0xEC:
8151 case 0xEE:
8152 case 0xEF:
8153 {
8154 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF }))))
8155 {
8156 return token_type::parse_error;
8157 }
8158 break;
8159 }
8160
8161 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8162 case 0xED:
8163 {
8164 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x9F, 0x80, 0xBF }))))
8165 {
8166 return token_type::parse_error;
8167 }
8168 break;
8169 }
8170
8171 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8172 case 0xF0:
8173 {
8174 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF }))))
8175 {
8176 return token_type::parse_error;
8177 }
8178 break;
8179 }
8180
8181 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8182 case 0xF1:
8183 case 0xF2:
8184 case 0xF3:
8185 {
8186 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF }))))
8187 {
8188 return token_type::parse_error;
8189 }
8190 break;
8191 }
8192
8193 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8194 case 0xF4:
8195 {
8196 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF }))))
8197 {
8198 return token_type::parse_error;
8199 }
8200 break;
8201 }
8202
8203 // remaining bytes (80..C1 and F5..FF) are ill-formed
8204 default:
8205 {
8206 error_message = "invalid string: ill-formed UTF-8 byte";
8207 return token_type::parse_error;
8208 }
8209 }
8210 }
8211 }
8212
8217 bool scan_comment()
8218 {
8219 switch (get())
8220 {
8221 // single-line comments skip input until a newline or EOF is read
8222 case '/':
8223 {
8224 while (true)
8225 {
8226 switch (get())
8227 {
8228 case '\n':
8229 case '\r':
8230 case char_traits<char_type>::eof():
8231 case '\0':
8232 return true;
8233
8234 default:
8235 break;
8236 }
8237 }
8238 }
8239
8240 // multi-line comments skip input until */ is read
8241 case '*':
8242 {
8243 while (true)
8244 {
8245 switch (get())
8246 {
8247 case char_traits<char_type>::eof():
8248 case '\0':
8249 {
8250 error_message = "invalid comment; missing closing '*/'";
8251 return false;
8252 }
8253
8254 case '*':
8255 {
8256 switch (get())
8257 {
8258 case '/':
8259 return true;
8260
8261 default:
8262 {
8263 unget();
8264 continue;
8265 }
8266 }
8267 }
8268
8269 default:
8270 continue;
8271 }
8272 }
8273 }
8274
8275 // unexpected character after reading '/'
8276 default:
8277 {
8278 error_message = "invalid comment; expecting '/' or '*' after '/'";
8279 return false;
8280 }
8281 }
8282 }
8283
8285 static void strtof(float& f, const char* str, char** endptr) noexcept
8286 {
8287 f = std::strtof(str, endptr);
8288 }
8289
8291 static void strtof(double& f, const char* str, char** endptr) noexcept
8292 {
8293 f = std::strtod(str, endptr);
8294 }
8295
8297 static void strtof(long double& f, const char* str, char** endptr) noexcept
8298 {
8299 f = std::strtold(str, endptr);
8300 }
8301
8342 token_type scan_number() // lgtm [cpp/use-of-goto]
8343 {
8344 // reset token_buffer to store the number's bytes
8345 reset();
8346
8347 // the type of the parsed number; initially set to unsigned; will be
8348 // changed if minus sign, decimal point or exponent is read
8349 token_type number_type = token_type::value_unsigned;
8350
8351 // state (init): we just found out we need to scan a number
8352 switch (current)
8353 {
8354 case '-':
8355 {
8356 add(current);
8357 goto scan_number_minus;
8358 }
8359
8360 case '0':
8361 {
8362 add(current);
8363 goto scan_number_zero;
8364 }
8365
8366 case '1':
8367 case '2':
8368 case '3':
8369 case '4':
8370 case '5':
8371 case '6':
8372 case '7':
8373 case '8':
8374 case '9':
8375 {
8376 add(current);
8377 goto scan_number_any1;
8378 }
8379
8380 // all other characters are rejected outside scan_number()
8381 default: // LCOV_EXCL_LINE
8382 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8383 }
8384
8385 scan_number_minus:
8386 // state: we just parsed a leading minus sign
8387 number_type = token_type::value_integer;
8388 switch (get())
8389 {
8390 case '0':
8391 {
8392 add(current);
8393 goto scan_number_zero;
8394 }
8395
8396 case '1':
8397 case '2':
8398 case '3':
8399 case '4':
8400 case '5':
8401 case '6':
8402 case '7':
8403 case '8':
8404 case '9':
8405 {
8406 add(current);
8407 goto scan_number_any1;
8408 }
8409
8410 default:
8411 {
8412 error_message = "invalid number; expected digit after '-'";
8413 return token_type::parse_error;
8414 }
8415 }
8416
8417 scan_number_zero:
8418 // state: we just parse a zero (maybe with a leading minus sign)
8419 switch (get())
8420 {
8421 case '.':
8422 {
8423 add(decimal_point_char);
8424 goto scan_number_decimal1;
8425 }
8426
8427 case 'e':
8428 case 'E':
8429 {
8430 add(current);
8431 goto scan_number_exponent;
8432 }
8433
8434 default:
8435 goto scan_number_done;
8436 }
8437
8438 scan_number_any1:
8439 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8440 switch (get())
8441 {
8442 case '0':
8443 case '1':
8444 case '2':
8445 case '3':
8446 case '4':
8447 case '5':
8448 case '6':
8449 case '7':
8450 case '8':
8451 case '9':
8452 {
8453 add(current);
8454 goto scan_number_any1;
8455 }
8456
8457 case '.':
8458 {
8459 add(decimal_point_char);
8460 goto scan_number_decimal1;
8461 }
8462
8463 case 'e':
8464 case 'E':
8465 {
8466 add(current);
8467 goto scan_number_exponent;
8468 }
8469
8470 default:
8471 goto scan_number_done;
8472 }
8473
8474 scan_number_decimal1:
8475 // state: we just parsed a decimal point
8476 number_type = token_type::value_float;
8477 switch (get())
8478 {
8479 case '0':
8480 case '1':
8481 case '2':
8482 case '3':
8483 case '4':
8484 case '5':
8485 case '6':
8486 case '7':
8487 case '8':
8488 case '9':
8489 {
8490 add(current);
8491 goto scan_number_decimal2;
8492 }
8493
8494 default:
8495 {
8496 error_message = "invalid number; expected digit after '.'";
8497 return token_type::parse_error;
8498 }
8499 }
8500
8501 scan_number_decimal2:
8502 // we just parsed at least one number after a decimal point
8503 switch (get())
8504 {
8505 case '0':
8506 case '1':
8507 case '2':
8508 case '3':
8509 case '4':
8510 case '5':
8511 case '6':
8512 case '7':
8513 case '8':
8514 case '9':
8515 {
8516 add(current);
8517 goto scan_number_decimal2;
8518 }
8519
8520 case 'e':
8521 case 'E':
8522 {
8523 add(current);
8524 goto scan_number_exponent;
8525 }
8526
8527 default:
8528 goto scan_number_done;
8529 }
8530
8531 scan_number_exponent:
8532 // we just parsed an exponent
8533 number_type = token_type::value_float;
8534 switch (get())
8535 {
8536 case '+':
8537 case '-':
8538 {
8539 add(current);
8540 goto scan_number_sign;
8541 }
8542
8543 case '0':
8544 case '1':
8545 case '2':
8546 case '3':
8547 case '4':
8548 case '5':
8549 case '6':
8550 case '7':
8551 case '8':
8552 case '9':
8553 {
8554 add(current);
8555 goto scan_number_any2;
8556 }
8557
8558 default:
8559 {
8560 error_message =
8561 "invalid number; expected '+', '-', or digit after exponent";
8562 return token_type::parse_error;
8563 }
8564 }
8565
8566 scan_number_sign:
8567 // we just parsed an exponent sign
8568 switch (get())
8569 {
8570 case '0':
8571 case '1':
8572 case '2':
8573 case '3':
8574 case '4':
8575 case '5':
8576 case '6':
8577 case '7':
8578 case '8':
8579 case '9':
8580 {
8581 add(current);
8582 goto scan_number_any2;
8583 }
8584
8585 default:
8586 {
8587 error_message = "invalid number; expected digit after exponent sign";
8588 return token_type::parse_error;
8589 }
8590 }
8591
8592 scan_number_any2:
8593 // we just parsed a number after the exponent or exponent sign
8594 switch (get())
8595 {
8596 case '0':
8597 case '1':
8598 case '2':
8599 case '3':
8600 case '4':
8601 case '5':
8602 case '6':
8603 case '7':
8604 case '8':
8605 case '9':
8606 {
8607 add(current);
8608 goto scan_number_any2;
8609 }
8610
8611 default:
8612 goto scan_number_done;
8613 }
8614
8615 scan_number_done:
8616 // unget the character after the number (we only read it to know that
8617 // we are done scanning a number)
8618 unget();
8619
8620 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8621 errno = 0;
8622
8623 // try to parse integers first and fall back to floats
8624 if (number_type == token_type::value_unsigned)
8625 {
8626 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8627
8628 // we checked the number format before
8629 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8630
8631 if (errno == 0)
8632 {
8633 value_unsigned = static_cast<number_unsigned_t>(x);
8634 if (value_unsigned == x)
8635 {
8636 return token_type::value_unsigned;
8637 }
8638 }
8639 }
8640 else if (number_type == token_type::value_integer)
8641 {
8642 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8643
8644 // we checked the number format before
8645 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8646
8647 if (errno == 0)
8648 {
8649 value_integer = static_cast<number_integer_t>(x);
8650 if (value_integer == x)
8651 {
8652 return token_type::value_integer;
8653 }
8654 }
8655 }
8656
8657 // this code is reached if we parse a floating-point number or if an
8658 // integer conversion above failed
8659 strtof(value_float, token_buffer.data(), &endptr);
8660
8661 // we checked the number format before
8662 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8663
8664 return token_type::value_float;
8665 }
8666
8673 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8674 token_type return_type)
8675 {
8676 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8677 for (std::size_t i = 1; i < length; ++i)
8678 {
8679 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8680 {
8681 error_message = "invalid literal";
8682 return token_type::parse_error;
8683 }
8684 }
8685 return return_type;
8686 }
8687
8689 // input management
8691
8693 void reset() noexcept
8694 {
8695 token_buffer.clear();
8696 token_string.clear();
8697 token_string.push_back(char_traits<char_type>::to_char_type(current));
8698 }
8699
8700 /*
8701 @brief get next character from the input
8702
8703 This function provides the interface to the used input adapter. It does
8704 not throw in case the input reached EOF, but returns a
8705 `char_traits<char>::eof()` in that case. Stores the scanned characters
8706 for use in error messages.
8707
8708 @return character read from the input
8709 */
8710 char_int_type get()
8711 {
8712 ++position.chars_read_total;
8713 ++position.chars_read_current_line;
8714
8715 if (next_unget)
8716 {
8717 // just reset the next_unget variable and work with current
8718 next_unget = false;
8719 }
8720 else
8721 {
8722 current = ia.get_character();
8723 }
8724
8725 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8726 {
8727 token_string.push_back(char_traits<char_type>::to_char_type(current));
8728 }
8729
8730 if (current == '\n')
8731 {
8732 ++position.lines_read;
8733 position.chars_read_current_line = 0;
8734 }
8735
8736 return current;
8737 }
8738
8747 void unget()
8748 {
8749 next_unget = true;
8750
8751 --position.chars_read_total;
8752
8753 // in case we "unget" a newline, we have to also decrement the lines_read
8754 if (position.chars_read_current_line == 0)
8755 {
8756 if (position.lines_read > 0)
8757 {
8758 --position.lines_read;
8759 }
8760 }
8761 else
8762 {
8763 --position.chars_read_current_line;
8764 }
8765
8766 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8767 {
8768 JSON_ASSERT(!token_string.empty());
8769 token_string.pop_back();
8770 }
8771 }
8772
8774 void add(char_int_type c)
8775 {
8776 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8777 }
8778
8779 public:
8781 // value getters
8783
8785 constexpr number_integer_t get_number_integer() const noexcept
8786 {
8787 return value_integer;
8788 }
8789
8791 constexpr number_unsigned_t get_number_unsigned() const noexcept
8792 {
8793 return value_unsigned;
8794 }
8795
8797 constexpr number_float_t get_number_float() const noexcept
8798 {
8799 return value_float;
8800 }
8801
8803 string_t& get_string()
8804 {
8805 return token_buffer;
8806 }
8807
8809 // diagnostics
8811
8813 constexpr position_t get_position() const noexcept
8814 {
8815 return position;
8816 }
8817
8821 std::string get_token_string() const
8822 {
8823 // escape control characters
8824 std::string result;
8825 for (const auto c : token_string)
8826 {
8827 if (static_cast<unsigned char>(c) <= '\x1F')
8828 {
8829 // escape control characters
8830 std::array<char, 9> cs{ {} };
8831 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8832 result += cs.data();
8833 }
8834 else
8835 {
8836 // add character as is
8837 result.push_back(static_cast<std::string::value_type>(c));
8838 }
8839 }
8840
8841 return result;
8842 }
8843
8846 constexpr const char* get_error_message() const noexcept
8847 {
8848 return error_message;
8849 }
8850
8852 // actual scanner
8854
8860 {
8861 if (get() == 0xEF)
8862 {
8863 // check if we completely parse the BOM
8864 return get() == 0xBB && get() == 0xBF;
8865 }
8866
8867 // the first character is not the beginning of the BOM; unget it to
8868 // process is later
8869 unget();
8870 return true;
8871 }
8872
8874 {
8875 do
8876 {
8877 get();
8878 } while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8879 }
8880
8882 {
8883 // initially, skip the BOM
8884 if (position.chars_read_total == 0 && !skip_bom())
8885 {
8886 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8887 return token_type::parse_error;
8888 }
8889
8890 // read next character and ignore whitespace
8891 skip_whitespace();
8892
8893 // ignore comments
8894 while (ignore_comments && current == '/')
8895 {
8896 if (!scan_comment())
8897 {
8898 return token_type::parse_error;
8899 }
8900
8901 // skip following whitespace
8902 skip_whitespace();
8903 }
8904
8905 switch (current)
8906 {
8907 // structural characters
8908 case '[':
8909 return token_type::begin_array;
8910 case ']':
8911 return token_type::end_array;
8912 case '{':
8913 return token_type::begin_object;
8914 case '}':
8915 return token_type::end_object;
8916 case ':':
8917 return token_type::name_separator;
8918 case ',':
8919 return token_type::value_separator;
8920
8921 // literals
8922 case 't':
8923 {
8924 std::array<char_type, 4> true_literal = { {static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')} };
8925 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8926 }
8927 case 'f':
8928 {
8929 std::array<char_type, 5> false_literal = { {static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')} };
8930 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8931 }
8932 case 'n':
8933 {
8934 std::array<char_type, 4> null_literal = { {static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')} };
8935 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8936 }
8937
8938 // string
8939 case '\"':
8940 return scan_string();
8941
8942 // number
8943 case '-':
8944 case '0':
8945 case '1':
8946 case '2':
8947 case '3':
8948 case '4':
8949 case '5':
8950 case '6':
8951 case '7':
8952 case '8':
8953 case '9':
8954 return scan_number();
8955
8956 // end of input (the null byte is needed when parsing from
8957 // string literals)
8958 case '\0':
8960 return token_type::end_of_input;
8961
8962 // error
8963 default:
8964 error_message = "invalid literal";
8965 return token_type::parse_error;
8966 }
8967 }
8968
8969 private:
8971 InputAdapterType ia;
8972
8974 const bool ignore_comments = false;
8975
8977 char_int_type current = char_traits<char_type>::eof();
8978
8980 bool next_unget = false;
8981
8983 position_t position{};
8984
8986 std::vector<char_type> token_string{};
8987
8989 string_t token_buffer{};
8990
8992 const char* error_message = "";
8993
8994 // number values
8995 number_integer_t value_integer = 0;
8996 number_unsigned_t value_unsigned = 0;
8997 number_float_t value_float = 0;
8998
9000 const char_int_type decimal_point_char = '.';
9001 };
9002
9003} // namespace detail
9005
9006// #include <nlohmann/detail/macro_scope.hpp>
9007
9008// #include <nlohmann/detail/meta/is_sax.hpp>
9009// __ _____ _____ _____
9010// __| | __| | | | JSON for Modern C++
9011// | | |__ | | | | | | version 3.11.3
9012// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9013//
9014// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
9015// SPDX-License-Identifier: MIT
9016
9017
9018
9019#include <cstdint> // size_t
9020#include <utility> // declval
9021#include <string> // string
9022
9023// #include <nlohmann/detail/abi_macros.hpp>
9024
9025// #include <nlohmann/detail/meta/detected.hpp>
9026
9027// #include <nlohmann/detail/meta/type_traits.hpp>
9028
9029
9031namespace detail
9032{
9033
9034 template<typename T>
9035 using null_function_t = decltype(std::declval<T&>().null());
9036
9037 template<typename T>
9039 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9040
9041 template<typename T, typename Integer>
9043 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9044
9045 template<typename T, typename Unsigned>
9047 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9048
9049 template<typename T, typename Float, typename String>
9050 using number_float_function_t = decltype(std::declval<T&>().number_float(
9051 std::declval<Float>(), std::declval<const String&>()));
9052
9053 template<typename T, typename String>
9055 decltype(std::declval<T&>().string(std::declval<String&>()));
9056
9057 template<typename T, typename Binary>
9059 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9060
9061 template<typename T>
9063 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9064
9065 template<typename T, typename String>
9067 decltype(std::declval<T&>().key(std::declval<String&>()));
9068
9069 template<typename T>
9070 using end_object_function_t = decltype(std::declval<T&>().end_object());
9071
9072 template<typename T>
9074 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9075
9076 template<typename T>
9077 using end_array_function_t = decltype(std::declval<T&>().end_array());
9078
9079 template<typename T, typename Exception>
9080 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9081 std::declval<std::size_t>(), std::declval<const std::string&>(),
9082 std::declval<const Exception&>()));
9083
9084 template<typename SAX, typename BasicJsonType>
9085 struct is_sax
9086 {
9087 private:
9089 "BasicJsonType must be of type basic_json<...>");
9090
9091 using number_integer_t = typename BasicJsonType::number_integer_t;
9092 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9093 using number_float_t = typename BasicJsonType::number_float_t;
9094 using string_t = typename BasicJsonType::string_t;
9095 using binary_t = typename BasicJsonType::binary_t;
9096 using exception_t = typename BasicJsonType::exception;
9097
9098 public:
9099 static constexpr bool value =
9113 };
9114
9115 template<typename SAX, typename BasicJsonType>
9117 {
9118 private:
9120 "BasicJsonType must be of type basic_json<...>");
9121
9122 using number_integer_t = typename BasicJsonType::number_integer_t;
9123 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9124 using number_float_t = typename BasicJsonType::number_float_t;
9125 using string_t = typename BasicJsonType::string_t;
9126 using binary_t = typename BasicJsonType::binary_t;
9127 using exception_t = typename BasicJsonType::exception;
9128
9129 public:
9131 "Missing/invalid function: bool null()");
9133 "Missing/invalid function: bool boolean(bool)");
9135 "Missing/invalid function: bool boolean(bool)");
9136 static_assert(
9138 number_integer_t>::value,
9139 "Missing/invalid function: bool number_integer(number_integer_t)");
9140 static_assert(
9142 number_unsigned_t>::value,
9143 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9144 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9145 number_float_t, string_t>::value,
9146 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9147 static_assert(
9149 "Missing/invalid function: bool string(string_t&)");
9150 static_assert(
9152 "Missing/invalid function: bool binary(binary_t&)");
9154 "Missing/invalid function: bool start_object(std::size_t)");
9156 "Missing/invalid function: bool key(string_t&)");
9158 "Missing/invalid function: bool end_object()");
9160 "Missing/invalid function: bool start_array(std::size_t)");
9162 "Missing/invalid function: bool end_array()");
9163 static_assert(
9165 "Missing/invalid function: bool parse_error(std::size_t, const "
9166 "std::string&, const exception&)");
9167 };
9168
9169} // namespace detail
9171
9172// #include <nlohmann/detail/meta/type_traits.hpp>
9173
9174// #include <nlohmann/detail/string_concat.hpp>
9175
9176// #include <nlohmann/detail/value_t.hpp>
9177
9178
9180namespace detail
9181{
9182
9185 {
9186 error,
9187 ignore,
9188 store
9189 };
9190
9198 static inline bool little_endianness(int num = 1) noexcept
9199 {
9200 return *reinterpret_cast<char*>(&num) == 1;
9201 }
9202
9204 // binary reader //
9206
9210 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9212 {
9213 using number_integer_t = typename BasicJsonType::number_integer_t;
9214 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9215 using number_float_t = typename BasicJsonType::number_float_t;
9216 using string_t = typename BasicJsonType::string_t;
9217 using binary_t = typename BasicJsonType::binary_t;
9218 using json_sax_t = SAX;
9219 using char_type = typename InputAdapterType::char_type;
9220 using char_int_type = typename char_traits<char_type>::int_type;
9221
9222 public:
9228 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9229 {
9231 }
9232
9233 // make class move-only
9235 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9237 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9238 ~binary_reader() = default;
9239
9249 bool sax_parse(const input_format_t format,
9250 json_sax_t* sax_,
9251 const bool strict = true,
9252 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9253 {
9254 sax = sax_;
9255 bool result = false;
9256
9257 switch (format)
9258 {
9260 result = parse_bson_internal();
9261 break;
9262
9264 result = parse_cbor_internal(true, tag_handler);
9265 break;
9266
9268 result = parse_msgpack_internal();
9269 break;
9270
9273 result = parse_ubjson_internal();
9274 break;
9275
9276 case input_format_t::json: // LCOV_EXCL_LINE
9277 default: // LCOV_EXCL_LINE
9278 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9279 }
9280
9281 // strict mode: next byte must be EOF
9282 if (result && strict)
9283 {
9284 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9285 {
9286 get_ignore_noop();
9287 }
9288 else
9289 {
9290 get();
9291 }
9292
9294 {
9295 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9296 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9297 }
9298 }
9299
9300 return result;
9301 }
9302
9303 private:
9305 // BSON //
9307
9312 bool parse_bson_internal()
9313 {
9314 std::int32_t document_size{};
9315 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9316
9317 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9318 {
9319 return false;
9320 }
9321
9322 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9323 {
9324 return false;
9325 }
9326
9327 return sax->end_object();
9328 }
9329
9337 bool get_bson_cstr(string_t& result)
9338 {
9339 auto out = std::back_inserter(result);
9340 while (true)
9341 {
9342 get();
9343 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9344 {
9345 return false;
9346 }
9347 if (current == 0x00)
9348 {
9349 return true;
9350 }
9351 *out++ = static_cast<typename string_t::value_type>(current);
9352 }
9353 }
9354
9366 template<typename NumberType>
9367 bool get_bson_string(const NumberType len, string_t& result)
9368 {
9369 if (JSON_HEDLEY_UNLIKELY(len < 1))
9370 {
9371 auto last_token = get_token_string();
9372 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9373 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9374 }
9375
9376 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9377 }
9378
9388 template<typename NumberType>
9389 bool get_bson_binary(const NumberType len, binary_t& result)
9390 {
9391 if (JSON_HEDLEY_UNLIKELY(len < 0))
9392 {
9393 auto last_token = get_token_string();
9394 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9395 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9396 }
9397
9398 // All BSON binary values have a subtype
9399 std::uint8_t subtype{};
9400 get_number<std::uint8_t>(input_format_t::bson, subtype);
9401 result.set_subtype(subtype);
9402
9403 return get_binary(input_format_t::bson, len, result);
9404 }
9405
9416 bool parse_bson_element_internal(const char_int_type element_type,
9417 const std::size_t element_type_parse_position)
9418 {
9419 switch (element_type)
9420 {
9421 case 0x01: // double
9422 {
9423 double number{};
9424 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9425 }
9426
9427 case 0x02: // string
9428 {
9429 std::int32_t len{};
9430 string_t value;
9431 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9432 }
9433
9434 case 0x03: // object
9435 {
9436 return parse_bson_internal();
9437 }
9438
9439 case 0x04: // array
9440 {
9441 return parse_bson_array();
9442 }
9443
9444 case 0x05: // binary
9445 {
9446 std::int32_t len{};
9447 binary_t value;
9448 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9449 }
9450
9451 case 0x08: // boolean
9452 {
9453 return sax->boolean(get() != 0);
9454 }
9455
9456 case 0x0A: // null
9457 {
9458 return sax->null();
9459 }
9460
9461 case 0x10: // int32
9462 {
9463 std::int32_t value{};
9464 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9465 }
9466
9467 case 0x12: // int64
9468 {
9469 std::int64_t value{};
9470 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9471 }
9472
9473 default: // anything else not supported (yet)
9474 {
9475 std::array<char, 3> cr{ {} };
9476 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9477 const std::string cr_str{ cr.data() };
9478 return sax->parse_error(element_type_parse_position, cr_str,
9479 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9480 }
9481 }
9482 }
9483
9496 bool parse_bson_element_list(const bool is_array)
9497 {
9498 string_t key;
9499
9500 while (auto element_type = get())
9501 {
9502 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9503 {
9504 return false;
9505 }
9506
9507 const std::size_t element_type_parse_position = chars_read;
9508 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9509 {
9510 return false;
9511 }
9512
9513 if (!is_array && !sax->key(key))
9514 {
9515 return false;
9516 }
9517
9518 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9519 {
9520 return false;
9521 }
9522
9523 // get_bson_cstr only appends
9524 key.clear();
9525 }
9526
9527 return true;
9528 }
9529
9534 bool parse_bson_array()
9535 {
9536 std::int32_t document_size{};
9537 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9538
9539 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9540 {
9541 return false;
9542 }
9543
9544 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9545 {
9546 return false;
9547 }
9548
9549 return sax->end_array();
9550 }
9551
9553 // CBOR //
9555
9564 bool parse_cbor_internal(const bool get_char,
9565 const cbor_tag_handler_t tag_handler)
9566 {
9567 switch (get_char ? get() : current)
9568 {
9569 // EOF
9570 case char_traits<char_type>::eof():
9571 return unexpect_eof(input_format_t::cbor, "value");
9572
9573 // Integer 0x00..0x17 (0..23)
9574 case 0x00:
9575 case 0x01:
9576 case 0x02:
9577 case 0x03:
9578 case 0x04:
9579 case 0x05:
9580 case 0x06:
9581 case 0x07:
9582 case 0x08:
9583 case 0x09:
9584 case 0x0A:
9585 case 0x0B:
9586 case 0x0C:
9587 case 0x0D:
9588 case 0x0E:
9589 case 0x0F:
9590 case 0x10:
9591 case 0x11:
9592 case 0x12:
9593 case 0x13:
9594 case 0x14:
9595 case 0x15:
9596 case 0x16:
9597 case 0x17:
9598 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9599
9600 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9601 {
9602 std::uint8_t number{};
9603 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9604 }
9605
9606 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9607 {
9608 std::uint16_t number{};
9609 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9610 }
9611
9612 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9613 {
9614 std::uint32_t number{};
9615 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9616 }
9617
9618 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9619 {
9620 std::uint64_t number{};
9621 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9622 }
9623
9624 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9625 case 0x20:
9626 case 0x21:
9627 case 0x22:
9628 case 0x23:
9629 case 0x24:
9630 case 0x25:
9631 case 0x26:
9632 case 0x27:
9633 case 0x28:
9634 case 0x29:
9635 case 0x2A:
9636 case 0x2B:
9637 case 0x2C:
9638 case 0x2D:
9639 case 0x2E:
9640 case 0x2F:
9641 case 0x30:
9642 case 0x31:
9643 case 0x32:
9644 case 0x33:
9645 case 0x34:
9646 case 0x35:
9647 case 0x36:
9648 case 0x37:
9649 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9650
9651 case 0x38: // Negative integer (one-byte uint8_t follows)
9652 {
9653 std::uint8_t number{};
9654 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9655 }
9656
9657 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9658 {
9659 std::uint16_t number{};
9660 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9661 }
9662
9663 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9664 {
9665 std::uint32_t number{};
9666 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9667 }
9668
9669 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9670 {
9671 std::uint64_t number{};
9672 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9673 - static_cast<number_integer_t>(number));
9674 }
9675
9676 // Binary data (0x00..0x17 bytes follow)
9677 case 0x40:
9678 case 0x41:
9679 case 0x42:
9680 case 0x43:
9681 case 0x44:
9682 case 0x45:
9683 case 0x46:
9684 case 0x47:
9685 case 0x48:
9686 case 0x49:
9687 case 0x4A:
9688 case 0x4B:
9689 case 0x4C:
9690 case 0x4D:
9691 case 0x4E:
9692 case 0x4F:
9693 case 0x50:
9694 case 0x51:
9695 case 0x52:
9696 case 0x53:
9697 case 0x54:
9698 case 0x55:
9699 case 0x56:
9700 case 0x57:
9701 case 0x58: // Binary data (one-byte uint8_t for n follows)
9702 case 0x59: // Binary data (two-byte uint16_t for n follow)
9703 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9704 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9705 case 0x5F: // Binary data (indefinite length)
9706 {
9707 binary_t b;
9708 return get_cbor_binary(b) && sax->binary(b);
9709 }
9710
9711 // UTF-8 string (0x00..0x17 bytes follow)
9712 case 0x60:
9713 case 0x61:
9714 case 0x62:
9715 case 0x63:
9716 case 0x64:
9717 case 0x65:
9718 case 0x66:
9719 case 0x67:
9720 case 0x68:
9721 case 0x69:
9722 case 0x6A:
9723 case 0x6B:
9724 case 0x6C:
9725 case 0x6D:
9726 case 0x6E:
9727 case 0x6F:
9728 case 0x70:
9729 case 0x71:
9730 case 0x72:
9731 case 0x73:
9732 case 0x74:
9733 case 0x75:
9734 case 0x76:
9735 case 0x77:
9736 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9737 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9738 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9739 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9740 case 0x7F: // UTF-8 string (indefinite length)
9741 {
9742 string_t s;
9743 return get_cbor_string(s) && sax->string(s);
9744 }
9745
9746 // array (0x00..0x17 data items follow)
9747 case 0x80:
9748 case 0x81:
9749 case 0x82:
9750 case 0x83:
9751 case 0x84:
9752 case 0x85:
9753 case 0x86:
9754 case 0x87:
9755 case 0x88:
9756 case 0x89:
9757 case 0x8A:
9758 case 0x8B:
9759 case 0x8C:
9760 case 0x8D:
9761 case 0x8E:
9762 case 0x8F:
9763 case 0x90:
9764 case 0x91:
9765 case 0x92:
9766 case 0x93:
9767 case 0x94:
9768 case 0x95:
9769 case 0x96:
9770 case 0x97:
9771 return get_cbor_array(
9772 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9773
9774 case 0x98: // array (one-byte uint8_t for n follows)
9775 {
9776 std::uint8_t len{};
9777 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9778 }
9779
9780 case 0x99: // array (two-byte uint16_t for n follow)
9781 {
9782 std::uint16_t len{};
9783 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9784 }
9785
9786 case 0x9A: // array (four-byte uint32_t for n follow)
9787 {
9788 std::uint32_t len{};
9789 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9790 }
9791
9792 case 0x9B: // array (eight-byte uint64_t for n follow)
9793 {
9794 std::uint64_t len{};
9795 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9796 }
9797
9798 case 0x9F: // array (indefinite length)
9799 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9800
9801 // map (0x00..0x17 pairs of data items follow)
9802 case 0xA0:
9803 case 0xA1:
9804 case 0xA2:
9805 case 0xA3:
9806 case 0xA4:
9807 case 0xA5:
9808 case 0xA6:
9809 case 0xA7:
9810 case 0xA8:
9811 case 0xA9:
9812 case 0xAA:
9813 case 0xAB:
9814 case 0xAC:
9815 case 0xAD:
9816 case 0xAE:
9817 case 0xAF:
9818 case 0xB0:
9819 case 0xB1:
9820 case 0xB2:
9821 case 0xB3:
9822 case 0xB4:
9823 case 0xB5:
9824 case 0xB6:
9825 case 0xB7:
9826 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9827
9828 case 0xB8: // map (one-byte uint8_t for n follows)
9829 {
9830 std::uint8_t len{};
9831 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9832 }
9833
9834 case 0xB9: // map (two-byte uint16_t for n follow)
9835 {
9836 std::uint16_t len{};
9837 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9838 }
9839
9840 case 0xBA: // map (four-byte uint32_t for n follow)
9841 {
9842 std::uint32_t len{};
9843 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9844 }
9845
9846 case 0xBB: // map (eight-byte uint64_t for n follow)
9847 {
9848 std::uint64_t len{};
9849 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9850 }
9851
9852 case 0xBF: // map (indefinite length)
9853 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9854
9855 case 0xC6: // tagged item
9856 case 0xC7:
9857 case 0xC8:
9858 case 0xC9:
9859 case 0xCA:
9860 case 0xCB:
9861 case 0xCC:
9862 case 0xCD:
9863 case 0xCE:
9864 case 0xCF:
9865 case 0xD0:
9866 case 0xD1:
9867 case 0xD2:
9868 case 0xD3:
9869 case 0xD4:
9870 case 0xD8: // tagged item (1 bytes follow)
9871 case 0xD9: // tagged item (2 bytes follow)
9872 case 0xDA: // tagged item (4 bytes follow)
9873 case 0xDB: // tagged item (8 bytes follow)
9874 {
9875 switch (tag_handler)
9876 {
9878 {
9879 auto last_token = get_token_string();
9880 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9881 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9882 }
9883
9885 {
9886 // ignore binary subtype
9887 switch (current)
9888 {
9889 case 0xD8:
9890 {
9891 std::uint8_t subtype_to_ignore{};
9892 get_number(input_format_t::cbor, subtype_to_ignore);
9893 break;
9894 }
9895 case 0xD9:
9896 {
9897 std::uint16_t subtype_to_ignore{};
9898 get_number(input_format_t::cbor, subtype_to_ignore);
9899 break;
9900 }
9901 case 0xDA:
9902 {
9903 std::uint32_t subtype_to_ignore{};
9904 get_number(input_format_t::cbor, subtype_to_ignore);
9905 break;
9906 }
9907 case 0xDB:
9908 {
9909 std::uint64_t subtype_to_ignore{};
9910 get_number(input_format_t::cbor, subtype_to_ignore);
9911 break;
9912 }
9913 default:
9914 break;
9915 }
9916 return parse_cbor_internal(true, tag_handler);
9917 }
9918
9920 {
9921 binary_t b;
9922 // use binary subtype and store in binary container
9923 switch (current)
9924 {
9925 case 0xD8:
9926 {
9927 std::uint8_t subtype{};
9928 get_number(input_format_t::cbor, subtype);
9930 break;
9931 }
9932 case 0xD9:
9933 {
9934 std::uint16_t subtype{};
9935 get_number(input_format_t::cbor, subtype);
9937 break;
9938 }
9939 case 0xDA:
9940 {
9941 std::uint32_t subtype{};
9942 get_number(input_format_t::cbor, subtype);
9944 break;
9945 }
9946 case 0xDB:
9947 {
9948 std::uint64_t subtype{};
9949 get_number(input_format_t::cbor, subtype);
9951 break;
9952 }
9953 default:
9954 return parse_cbor_internal(true, tag_handler);
9955 }
9956 get();
9957 return get_cbor_binary(b) && sax->binary(b);
9958 }
9959
9960 default: // LCOV_EXCL_LINE
9961 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9962 return false; // LCOV_EXCL_LINE
9963 }
9964 }
9965
9966 case 0xF4: // false
9967 return sax->boolean(false);
9968
9969 case 0xF5: // true
9970 return sax->boolean(true);
9971
9972 case 0xF6: // null
9973 return sax->null();
9974
9975 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9976 {
9977 const auto byte1_raw = get();
9978 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9979 {
9980 return false;
9981 }
9982 const auto byte2_raw = get();
9983 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9984 {
9985 return false;
9986 }
9987
9988 const auto byte1 = static_cast<unsigned char>(byte1_raw);
9989 const auto byte2 = static_cast<unsigned char>(byte2_raw);
9990
9991 // code from RFC 7049, Appendix D, Figure 3:
9992 // As half-precision floating-point numbers were only added
9993 // to IEEE 754 in 2008, today's programming platforms often
9994 // still only have limited support for them. It is very
9995 // easy to include at least decoding support for them even
9996 // without such support. An example of a small decoder for
9997 // half-precision floating-point numbers in the C language
9998 // is shown in Fig. 3.
9999 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10000 const double val = [&half]
10001 {
10002 const int exp = (half >> 10u) & 0x1Fu;
10003 const unsigned int mant = half & 0x3FFu;
10004 JSON_ASSERT(0 <= exp && exp <= 32);
10005 JSON_ASSERT(mant <= 1024);
10006 switch (exp)
10007 {
10008 case 0:
10009 return std::ldexp(mant, -24);
10010 case 31:
10011 return (mant == 0)
10012 ? std::numeric_limits<double>::infinity()
10013 : std::numeric_limits<double>::quiet_NaN();
10014 default:
10015 return std::ldexp(mant + 1024, exp - 25);
10016 }
10017 }();
10018 return sax->number_float((half & 0x8000u) != 0
10019 ? static_cast<number_float_t>(-val)
10020 : static_cast<number_float_t>(val), "");
10021 }
10022
10023 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10024 {
10025 float number{};
10026 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10027 }
10028
10029 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10030 {
10031 double number{};
10032 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10033 }
10034
10035 default: // anything else (0xFF is handled inside the other types)
10036 {
10037 auto last_token = get_token_string();
10038 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10039 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10040 }
10041 }
10042 }
10043
10055 bool get_cbor_string(string_t& result)
10056 {
10057 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10058 {
10059 return false;
10060 }
10061
10062 switch (current)
10063 {
10064 // UTF-8 string (0x00..0x17 bytes follow)
10065 case 0x60:
10066 case 0x61:
10067 case 0x62:
10068 case 0x63:
10069 case 0x64:
10070 case 0x65:
10071 case 0x66:
10072 case 0x67:
10073 case 0x68:
10074 case 0x69:
10075 case 0x6A:
10076 case 0x6B:
10077 case 0x6C:
10078 case 0x6D:
10079 case 0x6E:
10080 case 0x6F:
10081 case 0x70:
10082 case 0x71:
10083 case 0x72:
10084 case 0x73:
10085 case 0x74:
10086 case 0x75:
10087 case 0x76:
10088 case 0x77:
10089 {
10090 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10091 }
10092
10093 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10094 {
10095 std::uint8_t len{};
10096 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10097 }
10098
10099 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10100 {
10101 std::uint16_t len{};
10102 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10103 }
10104
10105 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10106 {
10107 std::uint32_t len{};
10108 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10109 }
10110
10111 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10112 {
10113 std::uint64_t len{};
10114 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10115 }
10116
10117 case 0x7F: // UTF-8 string (indefinite length)
10118 {
10119 while (get() != 0xFF)
10120 {
10121 string_t chunk;
10122 if (!get_cbor_string(chunk))
10123 {
10124 return false;
10125 }
10126 result.append(chunk);
10127 }
10128 return true;
10129 }
10130
10131 default:
10132 {
10133 auto last_token = get_token_string();
10134 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10135 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10136 }
10137 }
10138 }
10139
10151 bool get_cbor_binary(binary_t& result)
10152 {
10153 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10154 {
10155 return false;
10156 }
10157
10158 switch (current)
10159 {
10160 // Binary data (0x00..0x17 bytes follow)
10161 case 0x40:
10162 case 0x41:
10163 case 0x42:
10164 case 0x43:
10165 case 0x44:
10166 case 0x45:
10167 case 0x46:
10168 case 0x47:
10169 case 0x48:
10170 case 0x49:
10171 case 0x4A:
10172 case 0x4B:
10173 case 0x4C:
10174 case 0x4D:
10175 case 0x4E:
10176 case 0x4F:
10177 case 0x50:
10178 case 0x51:
10179 case 0x52:
10180 case 0x53:
10181 case 0x54:
10182 case 0x55:
10183 case 0x56:
10184 case 0x57:
10185 {
10186 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10187 }
10188
10189 case 0x58: // Binary data (one-byte uint8_t for n follows)
10190 {
10191 std::uint8_t len{};
10192 return get_number(input_format_t::cbor, len) &&
10193 get_binary(input_format_t::cbor, len, result);
10194 }
10195
10196 case 0x59: // Binary data (two-byte uint16_t for n follow)
10197 {
10198 std::uint16_t len{};
10199 return get_number(input_format_t::cbor, len) &&
10200 get_binary(input_format_t::cbor, len, result);
10201 }
10202
10203 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10204 {
10205 std::uint32_t len{};
10206 return get_number(input_format_t::cbor, len) &&
10207 get_binary(input_format_t::cbor, len, result);
10208 }
10209
10210 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10211 {
10212 std::uint64_t len{};
10213 return get_number(input_format_t::cbor, len) &&
10214 get_binary(input_format_t::cbor, len, result);
10215 }
10216
10217 case 0x5F: // Binary data (indefinite length)
10218 {
10219 while (get() != 0xFF)
10220 {
10221 binary_t chunk;
10222 if (!get_cbor_binary(chunk))
10223 {
10224 return false;
10225 }
10226 result.insert(result.end(), chunk.begin(), chunk.end());
10227 }
10228 return true;
10229 }
10230
10231 default:
10232 {
10233 auto last_token = get_token_string();
10234 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10235 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10236 }
10237 }
10238 }
10239
10246 bool get_cbor_array(const std::size_t len,
10247 const cbor_tag_handler_t tag_handler)
10248 {
10249 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10250 {
10251 return false;
10252 }
10253
10254 if (len != static_cast<std::size_t>(-1))
10255 {
10256 for (std::size_t i = 0; i < len; ++i)
10257 {
10258 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10259 {
10260 return false;
10261 }
10262 }
10263 }
10264 else
10265 {
10266 while (get() != 0xFF)
10267 {
10268 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10269 {
10270 return false;
10271 }
10272 }
10273 }
10274
10275 return sax->end_array();
10276 }
10277
10284 bool get_cbor_object(const std::size_t len,
10285 const cbor_tag_handler_t tag_handler)
10286 {
10287 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10288 {
10289 return false;
10290 }
10291
10292 if (len != 0)
10293 {
10294 string_t key;
10295 if (len != static_cast<std::size_t>(-1))
10296 {
10297 for (std::size_t i = 0; i < len; ++i)
10298 {
10299 get();
10300 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10301 {
10302 return false;
10303 }
10304
10305 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10306 {
10307 return false;
10308 }
10309 key.clear();
10310 }
10311 }
10312 else
10313 {
10314 while (get() != 0xFF)
10315 {
10316 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10317 {
10318 return false;
10319 }
10320
10321 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10322 {
10323 return false;
10324 }
10325 key.clear();
10326 }
10327 }
10328 }
10329
10330 return sax->end_object();
10331 }
10332
10334 // MsgPack //
10336
10340 bool parse_msgpack_internal()
10341 {
10342 switch (get())
10343 {
10344 // EOF
10345 case char_traits<char_type>::eof():
10346 return unexpect_eof(input_format_t::msgpack, "value");
10347
10348 // positive fixint
10349 case 0x00:
10350 case 0x01:
10351 case 0x02:
10352 case 0x03:
10353 case 0x04:
10354 case 0x05:
10355 case 0x06:
10356 case 0x07:
10357 case 0x08:
10358 case 0x09:
10359 case 0x0A:
10360 case 0x0B:
10361 case 0x0C:
10362 case 0x0D:
10363 case 0x0E:
10364 case 0x0F:
10365 case 0x10:
10366 case 0x11:
10367 case 0x12:
10368 case 0x13:
10369 case 0x14:
10370 case 0x15:
10371 case 0x16:
10372 case 0x17:
10373 case 0x18:
10374 case 0x19:
10375 case 0x1A:
10376 case 0x1B:
10377 case 0x1C:
10378 case 0x1D:
10379 case 0x1E:
10380 case 0x1F:
10381 case 0x20:
10382 case 0x21:
10383 case 0x22:
10384 case 0x23:
10385 case 0x24:
10386 case 0x25:
10387 case 0x26:
10388 case 0x27:
10389 case 0x28:
10390 case 0x29:
10391 case 0x2A:
10392 case 0x2B:
10393 case 0x2C:
10394 case 0x2D:
10395 case 0x2E:
10396 case 0x2F:
10397 case 0x30:
10398 case 0x31:
10399 case 0x32:
10400 case 0x33:
10401 case 0x34:
10402 case 0x35:
10403 case 0x36:
10404 case 0x37:
10405 case 0x38:
10406 case 0x39:
10407 case 0x3A:
10408 case 0x3B:
10409 case 0x3C:
10410 case 0x3D:
10411 case 0x3E:
10412 case 0x3F:
10413 case 0x40:
10414 case 0x41:
10415 case 0x42:
10416 case 0x43:
10417 case 0x44:
10418 case 0x45:
10419 case 0x46:
10420 case 0x47:
10421 case 0x48:
10422 case 0x49:
10423 case 0x4A:
10424 case 0x4B:
10425 case 0x4C:
10426 case 0x4D:
10427 case 0x4E:
10428 case 0x4F:
10429 case 0x50:
10430 case 0x51:
10431 case 0x52:
10432 case 0x53:
10433 case 0x54:
10434 case 0x55:
10435 case 0x56:
10436 case 0x57:
10437 case 0x58:
10438 case 0x59:
10439 case 0x5A:
10440 case 0x5B:
10441 case 0x5C:
10442 case 0x5D:
10443 case 0x5E:
10444 case 0x5F:
10445 case 0x60:
10446 case 0x61:
10447 case 0x62:
10448 case 0x63:
10449 case 0x64:
10450 case 0x65:
10451 case 0x66:
10452 case 0x67:
10453 case 0x68:
10454 case 0x69:
10455 case 0x6A:
10456 case 0x6B:
10457 case 0x6C:
10458 case 0x6D:
10459 case 0x6E:
10460 case 0x6F:
10461 case 0x70:
10462 case 0x71:
10463 case 0x72:
10464 case 0x73:
10465 case 0x74:
10466 case 0x75:
10467 case 0x76:
10468 case 0x77:
10469 case 0x78:
10470 case 0x79:
10471 case 0x7A:
10472 case 0x7B:
10473 case 0x7C:
10474 case 0x7D:
10475 case 0x7E:
10476 case 0x7F:
10477 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10478
10479 // fixmap
10480 case 0x80:
10481 case 0x81:
10482 case 0x82:
10483 case 0x83:
10484 case 0x84:
10485 case 0x85:
10486 case 0x86:
10487 case 0x87:
10488 case 0x88:
10489 case 0x89:
10490 case 0x8A:
10491 case 0x8B:
10492 case 0x8C:
10493 case 0x8D:
10494 case 0x8E:
10495 case 0x8F:
10496 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10497
10498 // fixarray
10499 case 0x90:
10500 case 0x91:
10501 case 0x92:
10502 case 0x93:
10503 case 0x94:
10504 case 0x95:
10505 case 0x96:
10506 case 0x97:
10507 case 0x98:
10508 case 0x99:
10509 case 0x9A:
10510 case 0x9B:
10511 case 0x9C:
10512 case 0x9D:
10513 case 0x9E:
10514 case 0x9F:
10515 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10516
10517 // fixstr
10518 case 0xA0:
10519 case 0xA1:
10520 case 0xA2:
10521 case 0xA3:
10522 case 0xA4:
10523 case 0xA5:
10524 case 0xA6:
10525 case 0xA7:
10526 case 0xA8:
10527 case 0xA9:
10528 case 0xAA:
10529 case 0xAB:
10530 case 0xAC:
10531 case 0xAD:
10532 case 0xAE:
10533 case 0xAF:
10534 case 0xB0:
10535 case 0xB1:
10536 case 0xB2:
10537 case 0xB3:
10538 case 0xB4:
10539 case 0xB5:
10540 case 0xB6:
10541 case 0xB7:
10542 case 0xB8:
10543 case 0xB9:
10544 case 0xBA:
10545 case 0xBB:
10546 case 0xBC:
10547 case 0xBD:
10548 case 0xBE:
10549 case 0xBF:
10550 case 0xD9: // str 8
10551 case 0xDA: // str 16
10552 case 0xDB: // str 32
10553 {
10554 string_t s;
10555 return get_msgpack_string(s) && sax->string(s);
10556 }
10557
10558 case 0xC0: // nil
10559 return sax->null();
10560
10561 case 0xC2: // false
10562 return sax->boolean(false);
10563
10564 case 0xC3: // true
10565 return sax->boolean(true);
10566
10567 case 0xC4: // bin 8
10568 case 0xC5: // bin 16
10569 case 0xC6: // bin 32
10570 case 0xC7: // ext 8
10571 case 0xC8: // ext 16
10572 case 0xC9: // ext 32
10573 case 0xD4: // fixext 1
10574 case 0xD5: // fixext 2
10575 case 0xD6: // fixext 4
10576 case 0xD7: // fixext 8
10577 case 0xD8: // fixext 16
10578 {
10579 binary_t b;
10580 return get_msgpack_binary(b) && sax->binary(b);
10581 }
10582
10583 case 0xCA: // float 32
10584 {
10585 float number{};
10586 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10587 }
10588
10589 case 0xCB: // float 64
10590 {
10591 double number{};
10592 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10593 }
10594
10595 case 0xCC: // uint 8
10596 {
10597 std::uint8_t number{};
10598 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10599 }
10600
10601 case 0xCD: // uint 16
10602 {
10603 std::uint16_t number{};
10604 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10605 }
10606
10607 case 0xCE: // uint 32
10608 {
10609 std::uint32_t number{};
10610 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10611 }
10612
10613 case 0xCF: // uint 64
10614 {
10615 std::uint64_t number{};
10616 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10617 }
10618
10619 case 0xD0: // int 8
10620 {
10621 std::int8_t number{};
10622 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10623 }
10624
10625 case 0xD1: // int 16
10626 {
10627 std::int16_t number{};
10628 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10629 }
10630
10631 case 0xD2: // int 32
10632 {
10633 std::int32_t number{};
10634 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10635 }
10636
10637 case 0xD3: // int 64
10638 {
10639 std::int64_t number{};
10640 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10641 }
10642
10643 case 0xDC: // array 16
10644 {
10645 std::uint16_t len{};
10646 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10647 }
10648
10649 case 0xDD: // array 32
10650 {
10651 std::uint32_t len{};
10652 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10653 }
10654
10655 case 0xDE: // map 16
10656 {
10657 std::uint16_t len{};
10658 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10659 }
10660
10661 case 0xDF: // map 32
10662 {
10663 std::uint32_t len{};
10664 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10665 }
10666
10667 // negative fixint
10668 case 0xE0:
10669 case 0xE1:
10670 case 0xE2:
10671 case 0xE3:
10672 case 0xE4:
10673 case 0xE5:
10674 case 0xE6:
10675 case 0xE7:
10676 case 0xE8:
10677 case 0xE9:
10678 case 0xEA:
10679 case 0xEB:
10680 case 0xEC:
10681 case 0xED:
10682 case 0xEE:
10683 case 0xEF:
10684 case 0xF0:
10685 case 0xF1:
10686 case 0xF2:
10687 case 0xF3:
10688 case 0xF4:
10689 case 0xF5:
10690 case 0xF6:
10691 case 0xF7:
10692 case 0xF8:
10693 case 0xF9:
10694 case 0xFA:
10695 case 0xFB:
10696 case 0xFC:
10697 case 0xFD:
10698 case 0xFE:
10699 case 0xFF:
10700 return sax->number_integer(static_cast<std::int8_t>(current));
10701
10702 default: // anything else
10703 {
10704 auto last_token = get_token_string();
10705 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10706 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10707 }
10708 }
10709 }
10710
10721 bool get_msgpack_string(string_t& result)
10722 {
10723 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10724 {
10725 return false;
10726 }
10727
10728 switch (current)
10729 {
10730 // fixstr
10731 case 0xA0:
10732 case 0xA1:
10733 case 0xA2:
10734 case 0xA3:
10735 case 0xA4:
10736 case 0xA5:
10737 case 0xA6:
10738 case 0xA7:
10739 case 0xA8:
10740 case 0xA9:
10741 case 0xAA:
10742 case 0xAB:
10743 case 0xAC:
10744 case 0xAD:
10745 case 0xAE:
10746 case 0xAF:
10747 case 0xB0:
10748 case 0xB1:
10749 case 0xB2:
10750 case 0xB3:
10751 case 0xB4:
10752 case 0xB5:
10753 case 0xB6:
10754 case 0xB7:
10755 case 0xB8:
10756 case 0xB9:
10757 case 0xBA:
10758 case 0xBB:
10759 case 0xBC:
10760 case 0xBD:
10761 case 0xBE:
10762 case 0xBF:
10763 {
10764 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10765 }
10766
10767 case 0xD9: // str 8
10768 {
10769 std::uint8_t len{};
10770 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10771 }
10772
10773 case 0xDA: // str 16
10774 {
10775 std::uint16_t len{};
10776 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10777 }
10778
10779 case 0xDB: // str 32
10780 {
10781 std::uint32_t len{};
10782 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10783 }
10784
10785 default:
10786 {
10787 auto last_token = get_token_string();
10788 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10789 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10790 }
10791 }
10792 }
10793
10804 bool get_msgpack_binary(binary_t& result)
10805 {
10806 // helper function to set the subtype
10807 auto assign_and_return_true = [&result](std::int8_t subtype)
10808 {
10809 result.set_subtype(static_cast<std::uint8_t>(subtype));
10810 return true;
10811 };
10812
10813 switch (current)
10814 {
10815 case 0xC4: // bin 8
10816 {
10817 std::uint8_t len{};
10818 return get_number(input_format_t::msgpack, len) &&
10819 get_binary(input_format_t::msgpack, len, result);
10820 }
10821
10822 case 0xC5: // bin 16
10823 {
10824 std::uint16_t len{};
10825 return get_number(input_format_t::msgpack, len) &&
10826 get_binary(input_format_t::msgpack, len, result);
10827 }
10828
10829 case 0xC6: // bin 32
10830 {
10831 std::uint32_t len{};
10832 return get_number(input_format_t::msgpack, len) &&
10833 get_binary(input_format_t::msgpack, len, result);
10834 }
10835
10836 case 0xC7: // ext 8
10837 {
10838 std::uint8_t len{};
10839 std::int8_t subtype{};
10840 return get_number(input_format_t::msgpack, len) &&
10841 get_number(input_format_t::msgpack, subtype) &&
10842 get_binary(input_format_t::msgpack, len, result) &&
10843 assign_and_return_true(subtype);
10844 }
10845
10846 case 0xC8: // ext 16
10847 {
10848 std::uint16_t len{};
10849 std::int8_t subtype{};
10850 return get_number(input_format_t::msgpack, len) &&
10851 get_number(input_format_t::msgpack, subtype) &&
10852 get_binary(input_format_t::msgpack, len, result) &&
10853 assign_and_return_true(subtype);
10854 }
10855
10856 case 0xC9: // ext 32
10857 {
10858 std::uint32_t len{};
10859 std::int8_t subtype{};
10860 return get_number(input_format_t::msgpack, len) &&
10861 get_number(input_format_t::msgpack, subtype) &&
10862 get_binary(input_format_t::msgpack, len, result) &&
10863 assign_and_return_true(subtype);
10864 }
10865
10866 case 0xD4: // fixext 1
10867 {
10868 std::int8_t subtype{};
10869 return get_number(input_format_t::msgpack, subtype) &&
10870 get_binary(input_format_t::msgpack, 1, result) &&
10871 assign_and_return_true(subtype);
10872 }
10873
10874 case 0xD5: // fixext 2
10875 {
10876 std::int8_t subtype{};
10877 return get_number(input_format_t::msgpack, subtype) &&
10878 get_binary(input_format_t::msgpack, 2, result) &&
10879 assign_and_return_true(subtype);
10880 }
10881
10882 case 0xD6: // fixext 4
10883 {
10884 std::int8_t subtype{};
10885 return get_number(input_format_t::msgpack, subtype) &&
10886 get_binary(input_format_t::msgpack, 4, result) &&
10887 assign_and_return_true(subtype);
10888 }
10889
10890 case 0xD7: // fixext 8
10891 {
10892 std::int8_t subtype{};
10893 return get_number(input_format_t::msgpack, subtype) &&
10894 get_binary(input_format_t::msgpack, 8, result) &&
10895 assign_and_return_true(subtype);
10896 }
10897
10898 case 0xD8: // fixext 16
10899 {
10900 std::int8_t subtype{};
10901 return get_number(input_format_t::msgpack, subtype) &&
10902 get_binary(input_format_t::msgpack, 16, result) &&
10903 assign_and_return_true(subtype);
10904 }
10905
10906 default: // LCOV_EXCL_LINE
10907 return false; // LCOV_EXCL_LINE
10908 }
10909 }
10910
10915 bool get_msgpack_array(const std::size_t len)
10916 {
10917 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10918 {
10919 return false;
10920 }
10921
10922 for (std::size_t i = 0; i < len; ++i)
10923 {
10924 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10925 {
10926 return false;
10927 }
10928 }
10929
10930 return sax->end_array();
10931 }
10932
10937 bool get_msgpack_object(const std::size_t len)
10938 {
10939 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10940 {
10941 return false;
10942 }
10943
10944 string_t key;
10945 for (std::size_t i = 0; i < len; ++i)
10946 {
10947 get();
10948 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10949 {
10950 return false;
10951 }
10952
10953 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10954 {
10955 return false;
10956 }
10957 key.clear();
10958 }
10959
10960 return sax->end_object();
10961 }
10962
10964 // UBJSON //
10966
10974 bool parse_ubjson_internal(const bool get_char = true)
10975 {
10976 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10977 }
10978
10993 bool get_ubjson_string(string_t& result, const bool get_char = true)
10994 {
10995 if (get_char)
10996 {
10997 get(); // TODO(niels): may we ignore N here?
10998 }
10999
11000 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11001 {
11002 return false;
11003 }
11004
11005 switch (current)
11006 {
11007 case 'U':
11008 {
11009 std::uint8_t len{};
11010 return get_number(input_format, len) && get_string(input_format, len, result);
11011 }
11012
11013 case 'i':
11014 {
11015 std::int8_t len{};
11016 return get_number(input_format, len) && get_string(input_format, len, result);
11017 }
11018
11019 case 'I':
11020 {
11021 std::int16_t len{};
11022 return get_number(input_format, len) && get_string(input_format, len, result);
11023 }
11024
11025 case 'l':
11026 {
11027 std::int32_t len{};
11028 return get_number(input_format, len) && get_string(input_format, len, result);
11029 }
11030
11031 case 'L':
11032 {
11033 std::int64_t len{};
11034 return get_number(input_format, len) && get_string(input_format, len, result);
11035 }
11036
11037 case 'u':
11038 {
11039 if (input_format != input_format_t::bjdata)
11040 {
11041 break;
11042 }
11043 std::uint16_t len{};
11044 return get_number(input_format, len) && get_string(input_format, len, result);
11045 }
11046
11047 case 'm':
11048 {
11049 if (input_format != input_format_t::bjdata)
11050 {
11051 break;
11052 }
11053 std::uint32_t len{};
11054 return get_number(input_format, len) && get_string(input_format, len, result);
11055 }
11056
11057 case 'M':
11058 {
11059 if (input_format != input_format_t::bjdata)
11060 {
11061 break;
11062 }
11063 std::uint64_t len{};
11064 return get_number(input_format, len) && get_string(input_format, len, result);
11065 }
11066
11067 default:
11068 break;
11069 }
11070 auto last_token = get_token_string();
11071 std::string message;
11072
11073 if (input_format != input_format_t::bjdata)
11074 {
11075 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11076 }
11077 else
11078 {
11079 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11080 }
11081 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11082 }
11083
11088 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11089 {
11090 std::pair<std::size_t, char_int_type> size_and_type;
11091 size_t dimlen = 0;
11092 bool no_ndarray = true;
11093
11094 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11095 {
11096 return false;
11097 }
11098
11099 if (size_and_type.first != npos)
11100 {
11101 if (size_and_type.second != 0)
11102 {
11103 if (size_and_type.second != 'N')
11104 {
11105 for (std::size_t i = 0; i < size_and_type.first; ++i)
11106 {
11107 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11108 {
11109 return false;
11110 }
11111 dim.push_back(dimlen);
11112 }
11113 }
11114 }
11115 else
11116 {
11117 for (std::size_t i = 0; i < size_and_type.first; ++i)
11118 {
11119 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11120 {
11121 return false;
11122 }
11123 dim.push_back(dimlen);
11124 }
11125 }
11126 }
11127 else
11128 {
11129 while (current != ']')
11130 {
11131 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11132 {
11133 return false;
11134 }
11135 dim.push_back(dimlen);
11136 get_ignore_noop();
11137 }
11138 }
11139 return true;
11140 }
11141
11153 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11154 {
11155 if (prefix == 0)
11156 {
11157 prefix = get_ignore_noop();
11158 }
11159
11160 switch (prefix)
11161 {
11162 case 'U':
11163 {
11164 std::uint8_t number{};
11165 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11166 {
11167 return false;
11168 }
11169 result = static_cast<std::size_t>(number);
11170 return true;
11171 }
11172
11173 case 'i':
11174 {
11175 std::int8_t number{};
11176 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11177 {
11178 return false;
11179 }
11180 if (number < 0)
11181 {
11182 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11183 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11184 }
11185 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11186 return true;
11187 }
11188
11189 case 'I':
11190 {
11191 std::int16_t number{};
11192 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11193 {
11194 return false;
11195 }
11196 if (number < 0)
11197 {
11198 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11199 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11200 }
11201 result = static_cast<std::size_t>(number);
11202 return true;
11203 }
11204
11205 case 'l':
11206 {
11207 std::int32_t number{};
11208 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11209 {
11210 return false;
11211 }
11212 if (number < 0)
11213 {
11214 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11215 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11216 }
11217 result = static_cast<std::size_t>(number);
11218 return true;
11219 }
11220
11221 case 'L':
11222 {
11223 std::int64_t number{};
11224 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11225 {
11226 return false;
11227 }
11228 if (number < 0)
11229 {
11230 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11231 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11232 }
11233 if (!value_in_range_of<std::size_t>(number))
11234 {
11235 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11236 exception_message(input_format, "integer value overflow", "size"), nullptr));
11237 }
11238 result = static_cast<std::size_t>(number);
11239 return true;
11240 }
11241
11242 case 'u':
11243 {
11244 if (input_format != input_format_t::bjdata)
11245 {
11246 break;
11247 }
11248 std::uint16_t number{};
11249 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11250 {
11251 return false;
11252 }
11253 result = static_cast<std::size_t>(number);
11254 return true;
11255 }
11256
11257 case 'm':
11258 {
11259 if (input_format != input_format_t::bjdata)
11260 {
11261 break;
11262 }
11263 std::uint32_t number{};
11264 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11265 {
11266 return false;
11267 }
11268 result = conditional_static_cast<std::size_t>(number);
11269 return true;
11270 }
11271
11272 case 'M':
11273 {
11274 if (input_format != input_format_t::bjdata)
11275 {
11276 break;
11277 }
11278 std::uint64_t number{};
11279 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11280 {
11281 return false;
11282 }
11283 if (!value_in_range_of<std::size_t>(number))
11284 {
11285 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11286 exception_message(input_format, "integer value overflow", "size"), nullptr));
11287 }
11289 return true;
11290 }
11291
11292 case '[':
11293 {
11294 if (input_format != input_format_t::bjdata)
11295 {
11296 break;
11297 }
11298 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11299 {
11300 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11301 }
11302 std::vector<size_t> dim;
11303 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11304 {
11305 return false;
11306 }
11307 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11308 {
11309 result = dim.at(dim.size() - 1);
11310 return true;
11311 }
11312 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11313 {
11314 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11315 {
11316 if (i == 0)
11317 {
11318 result = 0;
11319 return true;
11320 }
11321 }
11322
11323 string_t key = "_ArraySize_";
11324 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11325 {
11326 return false;
11327 }
11328 result = 1;
11329 for (auto i : dim)
11330 {
11331 result *= i;
11332 if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
11333 {
11334 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
11335 }
11336 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11337 {
11338 return false;
11339 }
11340 }
11341 is_ndarray = true;
11342 return sax->end_array();
11343 }
11344 result = 0;
11345 return true;
11346 }
11347
11348 default:
11349 break;
11350 }
11351 auto last_token = get_token_string();
11352 std::string message;
11353
11354 if (input_format != input_format_t::bjdata)
11355 {
11356 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11357 }
11358 else
11359 {
11360 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11361 }
11362 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11363 }
11364
11376 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11377 {
11378 result.first = npos; // size
11379 result.second = 0; // type
11380 bool is_ndarray = false;
11381
11382 get_ignore_noop();
11383
11384 if (current == '$')
11385 {
11386 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11387 if (input_format == input_format_t::bjdata
11388 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11389 {
11390 auto last_token = get_token_string();
11391 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11392 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11393 }
11394
11395 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11396 {
11397 return false;
11398 }
11399
11400 get_ignore_noop();
11401 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11402 {
11403 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11404 {
11405 return false;
11406 }
11407 auto last_token = get_token_string();
11408 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11409 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11410 }
11411
11412 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11413 if (input_format == input_format_t::bjdata && is_ndarray)
11414 {
11415 if (inside_ndarray)
11416 {
11417 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11418 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11419 }
11420 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11421 }
11422 return is_error;
11423 }
11424
11425 if (current == '#')
11426 {
11427 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11428 if (input_format == input_format_t::bjdata && is_ndarray)
11429 {
11430 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11431 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11432 }
11433 return is_error;
11434 }
11435
11436 return true;
11437 }
11438
11443 bool get_ubjson_value(const char_int_type prefix)
11444 {
11445 switch (prefix)
11446 {
11447 case char_traits<char_type>::eof(): // EOF
11448 return unexpect_eof(input_format, "value");
11449
11450 case 'T': // true
11451 return sax->boolean(true);
11452 case 'F': // false
11453 return sax->boolean(false);
11454
11455 case 'Z': // null
11456 return sax->null();
11457
11458 case 'U':
11459 {
11460 std::uint8_t number{};
11461 return get_number(input_format, number) && sax->number_unsigned(number);
11462 }
11463
11464 case 'i':
11465 {
11466 std::int8_t number{};
11467 return get_number(input_format, number) && sax->number_integer(number);
11468 }
11469
11470 case 'I':
11471 {
11472 std::int16_t number{};
11473 return get_number(input_format, number) && sax->number_integer(number);
11474 }
11475
11476 case 'l':
11477 {
11478 std::int32_t number{};
11479 return get_number(input_format, number) && sax->number_integer(number);
11480 }
11481
11482 case 'L':
11483 {
11484 std::int64_t number{};
11485 return get_number(input_format, number) && sax->number_integer(number);
11486 }
11487
11488 case 'u':
11489 {
11490 if (input_format != input_format_t::bjdata)
11491 {
11492 break;
11493 }
11494 std::uint16_t number{};
11495 return get_number(input_format, number) && sax->number_unsigned(number);
11496 }
11497
11498 case 'm':
11499 {
11500 if (input_format != input_format_t::bjdata)
11501 {
11502 break;
11503 }
11504 std::uint32_t number{};
11505 return get_number(input_format, number) && sax->number_unsigned(number);
11506 }
11507
11508 case 'M':
11509 {
11510 if (input_format != input_format_t::bjdata)
11511 {
11512 break;
11513 }
11514 std::uint64_t number{};
11515 return get_number(input_format, number) && sax->number_unsigned(number);
11516 }
11517
11518 case 'h':
11519 {
11520 if (input_format != input_format_t::bjdata)
11521 {
11522 break;
11523 }
11524 const auto byte1_raw = get();
11525 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11526 {
11527 return false;
11528 }
11529 const auto byte2_raw = get();
11530 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11531 {
11532 return false;
11533 }
11534
11535 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11536 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11537
11538 // code from RFC 7049, Appendix D, Figure 3:
11539 // As half-precision floating-point numbers were only added
11540 // to IEEE 754 in 2008, today's programming platforms often
11541 // still only have limited support for them. It is very
11542 // easy to include at least decoding support for them even
11543 // without such support. An example of a small decoder for
11544 // half-precision floating-point numbers in the C language
11545 // is shown in Fig. 3.
11546 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11547 const double val = [&half]
11548 {
11549 const int exp = (half >> 10u) & 0x1Fu;
11550 const unsigned int mant = half & 0x3FFu;
11551 JSON_ASSERT(0 <= exp && exp <= 32);
11552 JSON_ASSERT(mant <= 1024);
11553 switch (exp)
11554 {
11555 case 0:
11556 return std::ldexp(mant, -24);
11557 case 31:
11558 return (mant == 0)
11559 ? std::numeric_limits<double>::infinity()
11560 : std::numeric_limits<double>::quiet_NaN();
11561 default:
11562 return std::ldexp(mant + 1024, exp - 25);
11563 }
11564 }();
11565 return sax->number_float((half & 0x8000u) != 0
11566 ? static_cast<number_float_t>(-val)
11567 : static_cast<number_float_t>(val), "");
11568 }
11569
11570 case 'd':
11571 {
11572 float number{};
11573 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11574 }
11575
11576 case 'D':
11577 {
11578 double number{};
11579 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11580 }
11581
11582 case 'H':
11583 {
11584 return get_ubjson_high_precision_number();
11585 }
11586
11587 case 'C': // char
11588 {
11589 get();
11590 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11591 {
11592 return false;
11593 }
11594 if (JSON_HEDLEY_UNLIKELY(current > 127))
11595 {
11596 auto last_token = get_token_string();
11597 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11598 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11599 }
11600 string_t s(1, static_cast<typename string_t::value_type>(current));
11601 return sax->string(s);
11602 }
11603
11604 case 'S': // string
11605 {
11606 string_t s;
11607 return get_ubjson_string(s) && sax->string(s);
11608 }
11609
11610 case '[': // array
11611 return get_ubjson_array();
11612
11613 case '{': // object
11614 return get_ubjson_object();
11615
11616 default: // anything else
11617 break;
11618 }
11619 auto last_token = get_token_string();
11620 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
11621 }
11622
11626 bool get_ubjson_array()
11627 {
11628 std::pair<std::size_t, char_int_type> size_and_type;
11629 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11630 {
11631 return false;
11632 }
11633
11634 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
11635 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11636
11637 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11638 {
11639 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
11640 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type& p, char_int_type t)
11641 {
11642 return p.first < t;
11643 });
11644 string_t key = "_ArrayType_";
11645 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11646 {
11647 auto last_token = get_token_string();
11648 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11649 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11650 }
11651
11652 string_t type = it->second; // sax->string() takes a reference
11653 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11654 {
11655 return false;
11656 }
11657
11658 if (size_and_type.second == 'C')
11659 {
11660 size_and_type.second = 'U';
11661 }
11662
11663 key = "_ArrayData_";
11664 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first)))
11665 {
11666 return false;
11667 }
11668
11669 for (std::size_t i = 0; i < size_and_type.first; ++i)
11670 {
11671 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11672 {
11673 return false;
11674 }
11675 }
11676
11677 return (sax->end_array() && sax->end_object());
11678 }
11679
11680 if (size_and_type.first != npos)
11681 {
11682 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11683 {
11684 return false;
11685 }
11686
11687 if (size_and_type.second != 0)
11688 {
11689 if (size_and_type.second != 'N')
11690 {
11691 for (std::size_t i = 0; i < size_and_type.first; ++i)
11692 {
11693 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11694 {
11695 return false;
11696 }
11697 }
11698 }
11699 }
11700 else
11701 {
11702 for (std::size_t i = 0; i < size_and_type.first; ++i)
11703 {
11704 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11705 {
11706 return false;
11707 }
11708 }
11709 }
11710 }
11711 else
11712 {
11713 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11714 {
11715 return false;
11716 }
11717
11718 while (current != ']')
11719 {
11720 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11721 {
11722 return false;
11723 }
11724 get_ignore_noop();
11725 }
11726 }
11727
11728 return sax->end_array();
11729 }
11730
11734 bool get_ubjson_object()
11735 {
11736 std::pair<std::size_t, char_int_type> size_and_type;
11737 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11738 {
11739 return false;
11740 }
11741
11742 // do not accept ND-array size in objects in BJData
11743 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11744 {
11745 auto last_token = get_token_string();
11746 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11747 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11748 }
11749
11750 string_t key;
11751 if (size_and_type.first != npos)
11752 {
11753 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11754 {
11755 return false;
11756 }
11757
11758 if (size_and_type.second != 0)
11759 {
11760 for (std::size_t i = 0; i < size_and_type.first; ++i)
11761 {
11762 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11763 {
11764 return false;
11765 }
11766 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11767 {
11768 return false;
11769 }
11770 key.clear();
11771 }
11772 }
11773 else
11774 {
11775 for (std::size_t i = 0; i < size_and_type.first; ++i)
11776 {
11777 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11778 {
11779 return false;
11780 }
11781 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11782 {
11783 return false;
11784 }
11785 key.clear();
11786 }
11787 }
11788 }
11789 else
11790 {
11791 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11792 {
11793 return false;
11794 }
11795
11796 while (current != '}')
11797 {
11798 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11799 {
11800 return false;
11801 }
11802 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11803 {
11804 return false;
11805 }
11806 get_ignore_noop();
11807 key.clear();
11808 }
11809 }
11810
11811 return sax->end_object();
11812 }
11813
11814 // Note, no reader for UBJSON binary types is implemented because they do
11815 // not exist
11816
11817 bool get_ubjson_high_precision_number()
11818 {
11819 // get size of following number string
11820 std::size_t size{};
11821 bool no_ndarray = true;
11822 auto res = get_ubjson_size_value(size, no_ndarray);
11823 if (JSON_HEDLEY_UNLIKELY(!res))
11824 {
11825 return res;
11826 }
11827
11828 // get number string
11829 std::vector<char> number_vector;
11830 for (std::size_t i = 0; i < size; ++i)
11831 {
11832 get();
11833 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11834 {
11835 return false;
11836 }
11837 number_vector.push_back(static_cast<char>(current));
11838 }
11839
11840 // parse number string
11841 using ia_type = decltype(detail::input_adapter(number_vector));
11842 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11843 const auto result_number = number_lexer.scan();
11844 const auto number_string = number_lexer.get_token_string();
11845 const auto result_remainder = number_lexer.scan();
11846
11847 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11848
11849 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11850 {
11851 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11852 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11853 }
11854
11855 switch (result_number)
11856 {
11857 case token_type::value_integer:
11858 return sax->number_integer(number_lexer.get_number_integer());
11859 case token_type::value_unsigned:
11860 return sax->number_unsigned(number_lexer.get_number_unsigned());
11861 case token_type::value_float:
11862 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11863 case token_type::uninitialized:
11864 case token_type::literal_true:
11865 case token_type::literal_false:
11866 case token_type::literal_null:
11867 case token_type::value_string:
11868 case token_type::begin_array:
11869 case token_type::begin_object:
11870 case token_type::end_array:
11871 case token_type::end_object:
11872 case token_type::name_separator:
11873 case token_type::value_separator:
11874 case token_type::parse_error:
11875 case token_type::end_of_input:
11876 case token_type::literal_or_value:
11877 default:
11878 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11879 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11880 }
11881 }
11882
11884 // Utility functions //
11886
11896 char_int_type get()
11897 {
11898 ++chars_read;
11899 return current = ia.get_character();
11900 }
11901
11905 char_int_type get_ignore_noop()
11906 {
11907 do
11908 {
11909 get();
11910 } while (current == 'N');
11911
11912 return current;
11913 }
11914
11915 /*
11916 @brief read a number from the input
11917
11918 @tparam NumberType the type of the number
11919 @param[in] format the current format (for diagnostics)
11920 @param[out] result number of type @a NumberType
11921
11922 @return whether conversion completed
11923
11924 @note This function needs to respect the system's endianness, because
11925 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11926 (big endian) and therefore need reordering on little endian systems.
11927 On the other hand, BSON and BJData use little endian and should reorder
11928 on big endian systems.
11929 */
11930 template<typename NumberType, bool InputIsLittleEndian = false>
11931 bool get_number(const input_format_t format, NumberType& result)
11932 {
11933 // step 1: read input into array with system's byte order
11934 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11935 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11936 {
11937 get();
11938 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11939 {
11940 return false;
11941 }
11942
11943 // reverse byte order prior to conversion if necessary
11944 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11945 {
11946 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11947 }
11948 else
11949 {
11950 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11951 }
11952 }
11953
11954 // step 2: convert array into number of type T and return
11955 std::memcpy(&result, vec.data(), sizeof(NumberType));
11956 return true;
11957 }
11958
11973 template<typename NumberType>
11974 bool get_string(const input_format_t format,
11975 const NumberType len,
11976 string_t& result)
11977 {
11978 bool success = true;
11979 for (NumberType i = 0; i < len; i++)
11980 {
11981 get();
11982 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11983 {
11984 success = false;
11985 break;
11986 }
11987 result.push_back(static_cast<typename string_t::value_type>(current));
11988 }
11989 return success;
11990 }
11991
12006 template<typename NumberType>
12007 bool get_binary(const input_format_t format,
12008 const NumberType len,
12009 binary_t& result)
12010 {
12011 bool success = true;
12012 for (NumberType i = 0; i < len; i++)
12013 {
12014 get();
12015 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12016 {
12017 success = false;
12018 break;
12019 }
12020 result.push_back(static_cast<std::uint8_t>(current));
12021 }
12022 return success;
12023 }
12024
12031 bool unexpect_eof(const input_format_t format, const char* context) const
12032 {
12033 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12034 {
12035 return sax->parse_error(chars_read, "<end of file>",
12036 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12037 }
12038 return true;
12039 }
12040
12044 std::string get_token_string() const
12045 {
12046 std::array<char, 3> cr{ {} };
12047 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12048 return std::string{ cr.data() };
12049 }
12050
12057 std::string exception_message(const input_format_t format,
12058 const std::string& detail,
12059 const std::string& context) const
12060 {
12061 std::string error_msg = "syntax error while parsing ";
12062
12063 switch (format)
12064 {
12066 error_msg += "CBOR";
12067 break;
12068
12070 error_msg += "MessagePack";
12071 break;
12072
12074 error_msg += "UBJSON";
12075 break;
12076
12078 error_msg += "BSON";
12079 break;
12080
12082 error_msg += "BJData";
12083 break;
12084
12085 case input_format_t::json: // LCOV_EXCL_LINE
12086 default: // LCOV_EXCL_LINE
12087 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12088 }
12089
12090 return concat(error_msg, ' ', context, ": ", detail);
12091 }
12092
12093 private:
12094 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12095
12097 InputAdapterType ia;
12098
12100 char_int_type current = char_traits<char_type>::eof();
12101
12103 std::size_t chars_read = 0;
12104
12106 const bool is_little_endian = little_endianness();
12107
12109 const input_format_t input_format = input_format_t::json;
12110
12112 json_sax_t* sax = nullptr;
12113
12114 // excluded markers in bjdata optimized type
12115#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12116 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12117
12118#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12119 make_array<bjd_type>( \
12120 bjd_type{'C', "char"}, \
12121 bjd_type{'D', "double"}, \
12122 bjd_type{'I', "int16"}, \
12123 bjd_type{'L', "int64"}, \
12124 bjd_type{'M', "uint64"}, \
12125 bjd_type{'U', "uint8"}, \
12126 bjd_type{'d', "single"}, \
12127 bjd_type{'i', "int8"}, \
12128 bjd_type{'l', "int32"}, \
12129 bjd_type{'m', "uint32"}, \
12130 bjd_type{'u', "uint16"})
12131
12133 // lookup tables
12134 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12135 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12137
12138 using bjd_type = std::pair<char_int_type, string_t>;
12139 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12140 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12142
12143#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12144#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12145 };
12146
12147#ifndef JSON_HAS_CPP_17
12148 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12149 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12150#endif
12151
12152} // namespace detail
12154
12155// #include <nlohmann/detail/input/input_adapters.hpp>
12156
12157// #include <nlohmann/detail/input/lexer.hpp>
12158
12159// #include <nlohmann/detail/input/parser.hpp>
12160// __ _____ _____ _____
12161// __| | __| | | | JSON for Modern C++
12162// | | |__ | | | | | | version 3.11.3
12163// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12164//
12165// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12166// SPDX-License-Identifier: MIT
12167
12168
12169
12170#include <cmath> // isfinite
12171#include <cstdint> // uint8_t
12172#include <functional> // function
12173#include <string> // string
12174#include <utility> // move
12175#include <vector> // vector
12176
12177// #include <nlohmann/detail/exceptions.hpp>
12178
12179// #include <nlohmann/detail/input/input_adapters.hpp>
12180
12181// #include <nlohmann/detail/input/json_sax.hpp>
12182
12183// #include <nlohmann/detail/input/lexer.hpp>
12184
12185// #include <nlohmann/detail/macro_scope.hpp>
12186
12187// #include <nlohmann/detail/meta/is_sax.hpp>
12188
12189// #include <nlohmann/detail/string_concat.hpp>
12190
12191// #include <nlohmann/detail/value_t.hpp>
12192
12193
12195namespace detail
12196{
12198 // parser //
12200
12201 enum class parse_event_t : std::uint8_t
12202 {
12206 object_end,
12210 array_end,
12212 key,
12214 value
12215 };
12216
12217 template<typename BasicJsonType>
12219 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12220
12226 template<typename BasicJsonType, typename InputAdapterType>
12228 {
12229 using number_integer_t = typename BasicJsonType::number_integer_t;
12230 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12231 using number_float_t = typename BasicJsonType::number_float_t;
12232 using string_t = typename BasicJsonType::string_t;
12234 using token_type = typename lexer_t::token_type;
12235
12236 public:
12238 explicit parser(InputAdapterType&& adapter,
12239 const parser_callback_t<BasicJsonType> cb = nullptr,
12240 const bool allow_exceptions_ = true,
12241 const bool skip_comments = false)
12242 : callback(cb)
12243 , m_lexer(std::move(adapter), skip_comments)
12244 , allow_exceptions(allow_exceptions_)
12245 {
12246 // read first token
12247 get_token();
12248 }
12249
12260 void parse(const bool strict, BasicJsonType& result)
12261 {
12262 if (callback)
12263 {
12264 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12265 sax_parse_internal(&sdp);
12266
12267 // in strict mode, input must be completely read
12268 if (strict && (get_token() != token_type::end_of_input))
12269 {
12270 sdp.parse_error(m_lexer.get_position(),
12271 m_lexer.get_token_string(),
12272 parse_error::create(101, m_lexer.get_position(),
12273 exception_message(token_type::end_of_input, "value"), nullptr));
12274 }
12275
12276 // in case of an error, return discarded value
12277 if (sdp.is_errored())
12278 {
12279 result = value_t::discarded;
12280 return;
12281 }
12282
12283 // set top-level value to null if it was discarded by the callback
12284 // function
12285 if (result.is_discarded())
12286 {
12287 result = nullptr;
12288 }
12289 }
12290 else
12291 {
12292 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12293 sax_parse_internal(&sdp);
12294
12295 // in strict mode, input must be completely read
12296 if (strict && (get_token() != token_type::end_of_input))
12297 {
12298 sdp.parse_error(m_lexer.get_position(),
12299 m_lexer.get_token_string(),
12300 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12301 }
12302
12303 // in case of an error, return discarded value
12304 if (sdp.is_errored())
12305 {
12306 result = value_t::discarded;
12307 return;
12308 }
12309 }
12310
12311 result.assert_invariant();
12312 }
12313
12320 bool accept(const bool strict = true)
12321 {
12323 return sax_parse(&sax_acceptor, strict);
12324 }
12325
12326 template<typename SAX>
12328 bool sax_parse(SAX* sax, const bool strict = true)
12329 {
12331 const bool result = sax_parse_internal(sax);
12332
12333 // strict mode: next byte must be EOF
12334 if (result && strict && (get_token() != token_type::end_of_input))
12335 {
12336 return sax->parse_error(m_lexer.get_position(),
12337 m_lexer.get_token_string(),
12338 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12339 }
12340
12341 return result;
12342 }
12343
12344 private:
12345 template<typename SAX>
12347 bool sax_parse_internal(SAX* sax)
12348 {
12349 // stack to remember the hierarchy of structured values we are parsing
12350 // true = array; false = object
12351 std::vector<bool> states;
12352 // value to avoid a goto (see comment where set to true)
12353 bool skip_to_state_evaluation = false;
12354
12355 while (true)
12356 {
12357 if (!skip_to_state_evaluation)
12358 {
12359 // invariant: get_token() was called before each iteration
12360 switch (last_token)
12361 {
12362 case token_type::begin_object:
12363 {
12364 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12365 {
12366 return false;
12367 }
12368
12369 // closing } -> we are done
12370 if (get_token() == token_type::end_object)
12371 {
12372 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12373 {
12374 return false;
12375 }
12376 break;
12377 }
12378
12379 // parse key
12380 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12381 {
12382 return sax->parse_error(m_lexer.get_position(),
12383 m_lexer.get_token_string(),
12384 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12385 }
12386 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12387 {
12388 return false;
12389 }
12390
12391 // parse separator (:)
12392 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12393 {
12394 return sax->parse_error(m_lexer.get_position(),
12395 m_lexer.get_token_string(),
12396 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12397 }
12398
12399 // remember we are now inside an object
12400 states.push_back(false);
12401
12402 // parse values
12403 get_token();
12404 continue;
12405 }
12406
12407 case token_type::begin_array:
12408 {
12409 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12410 {
12411 return false;
12412 }
12413
12414 // closing ] -> we are done
12415 if (get_token() == token_type::end_array)
12416 {
12417 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12418 {
12419 return false;
12420 }
12421 break;
12422 }
12423
12424 // remember we are now inside an array
12425 states.push_back(true);
12426
12427 // parse values (no need to call get_token)
12428 continue;
12429 }
12430
12431 case token_type::value_float:
12432 {
12433 const auto res = m_lexer.get_number_float();
12434
12435 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12436 {
12437 return sax->parse_error(m_lexer.get_position(),
12438 m_lexer.get_token_string(),
12439 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12440 }
12441
12442 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12443 {
12444 return false;
12445 }
12446
12447 break;
12448 }
12449
12450 case token_type::literal_false:
12451 {
12452 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12453 {
12454 return false;
12455 }
12456 break;
12457 }
12458
12459 case token_type::literal_null:
12460 {
12461 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12462 {
12463 return false;
12464 }
12465 break;
12466 }
12467
12468 case token_type::literal_true:
12469 {
12470 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12471 {
12472 return false;
12473 }
12474 break;
12475 }
12476
12477 case token_type::value_integer:
12478 {
12479 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12480 {
12481 return false;
12482 }
12483 break;
12484 }
12485
12486 case token_type::value_string:
12487 {
12488 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12489 {
12490 return false;
12491 }
12492 break;
12493 }
12494
12495 case token_type::value_unsigned:
12496 {
12497 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12498 {
12499 return false;
12500 }
12501 break;
12502 }
12503
12504 case token_type::parse_error:
12505 {
12506 // using "uninitialized" to avoid "expected" message
12507 return sax->parse_error(m_lexer.get_position(),
12508 m_lexer.get_token_string(),
12509 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12510 }
12511 case token_type::end_of_input:
12512 {
12514 {
12515 return sax->parse_error(m_lexer.get_position(),
12516 m_lexer.get_token_string(),
12517 parse_error::create(101, m_lexer.get_position(),
12518 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12519 }
12520
12521 return sax->parse_error(m_lexer.get_position(),
12522 m_lexer.get_token_string(),
12523 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12524 }
12525 case token_type::uninitialized:
12526 case token_type::end_array:
12527 case token_type::end_object:
12528 case token_type::name_separator:
12529 case token_type::value_separator:
12530 case token_type::literal_or_value:
12531 default: // the last token was unexpected
12532 {
12533 return sax->parse_error(m_lexer.get_position(),
12534 m_lexer.get_token_string(),
12535 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12536 }
12537 }
12538 }
12539 else
12540 {
12541 skip_to_state_evaluation = false;
12542 }
12543
12544 // we reached this line after we successfully parsed a value
12545 if (states.empty())
12546 {
12547 // empty stack: we reached the end of the hierarchy: done
12548 return true;
12549 }
12550
12551 if (states.back()) // array
12552 {
12553 // comma -> next value
12554 if (get_token() == token_type::value_separator)
12555 {
12556 // parse a new value
12557 get_token();
12558 continue;
12559 }
12560
12561 // closing ]
12562 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12563 {
12564 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12565 {
12566 return false;
12567 }
12568
12569 // We are done with this array. Before we can parse a
12570 // new value, we need to evaluate the new state first.
12571 // By setting skip_to_state_evaluation to false, we
12572 // are effectively jumping to the beginning of this if.
12573 JSON_ASSERT(!states.empty());
12574 states.pop_back();
12575 skip_to_state_evaluation = true;
12576 continue;
12577 }
12578
12579 return sax->parse_error(m_lexer.get_position(),
12580 m_lexer.get_token_string(),
12581 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12582 }
12583
12584 // states.back() is false -> object
12585
12586 // comma -> next value
12587 if (get_token() == token_type::value_separator)
12588 {
12589 // parse key
12590 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12591 {
12592 return sax->parse_error(m_lexer.get_position(),
12593 m_lexer.get_token_string(),
12594 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12595 }
12596
12597 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12598 {
12599 return false;
12600 }
12601
12602 // parse separator (:)
12603 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12604 {
12605 return sax->parse_error(m_lexer.get_position(),
12606 m_lexer.get_token_string(),
12607 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12608 }
12609
12610 // parse values
12611 get_token();
12612 continue;
12613 }
12614
12615 // closing }
12616 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12617 {
12618 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12619 {
12620 return false;
12621 }
12622
12623 // We are done with this object. Before we can parse a
12624 // new value, we need to evaluate the new state first.
12625 // By setting skip_to_state_evaluation to false, we
12626 // are effectively jumping to the beginning of this if.
12627 JSON_ASSERT(!states.empty());
12628 states.pop_back();
12629 skip_to_state_evaluation = true;
12630 continue;
12631 }
12632
12633 return sax->parse_error(m_lexer.get_position(),
12634 m_lexer.get_token_string(),
12635 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12636 }
12637 }
12638
12640 token_type get_token()
12641 {
12642 return last_token = m_lexer.scan();
12643 }
12644
12645 std::string exception_message(const token_type expected, const std::string& context)
12646 {
12647 std::string error_msg = "syntax error ";
12648
12649 if (!context.empty())
12650 {
12651 error_msg += concat("while parsing ", context, ' ');
12652 }
12653
12654 error_msg += "- ";
12655
12656 if (last_token == token_type::parse_error)
12657 {
12658 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12659 m_lexer.get_token_string(), '\'');
12660 }
12661 else
12662 {
12663 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12664 }
12665
12666 if (expected != token_type::uninitialized)
12667 {
12668 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12669 }
12670
12671 return error_msg;
12672 }
12673
12674 private:
12676 const parser_callback_t<BasicJsonType> callback = nullptr;
12678 token_type last_token = token_type::uninitialized;
12680 lexer_t m_lexer;
12682 const bool allow_exceptions = true;
12683 };
12684
12685} // namespace detail
12687
12688// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12689// __ _____ _____ _____
12690// __| | __| | | | JSON for Modern C++
12691// | | |__ | | | | | | version 3.11.3
12692// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12693//
12694// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12695// SPDX-License-Identifier: MIT
12696
12697
12698
12699// #include <nlohmann/detail/abi_macros.hpp>
12700
12701// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12702// __ _____ _____ _____
12703// __| | __| | | | JSON for Modern C++
12704// | | |__ | | | | | | version 3.11.3
12705// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12706//
12707// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12708// SPDX-License-Identifier: MIT
12709
12710
12711
12712#include <cstddef> // ptrdiff_t
12713#include <limits> // numeric_limits
12714
12715// #include <nlohmann/detail/macro_scope.hpp>
12716
12717
12719namespace detail
12720{
12721
12722 /*
12723 @brief an iterator for primitive JSON types
12724
12725 This class models an iterator for primitive JSON types (boolean, number,
12726 string). It's only purpose is to allow the iterator/const_iterator classes
12727 to "iterate" over primitive values. Internally, the iterator is modeled by
12728 a `difference_type` variable. Value begin_value (`0`) models the begin,
12729 end_value (`1`) models past the end.
12730 */
12732 {
12733 private:
12734 using difference_type = std::ptrdiff_t;
12735 static constexpr difference_type begin_value = 0;
12736 static constexpr difference_type end_value = begin_value + 1;
12737
12740 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12741
12742 public:
12743 constexpr difference_type get_value() const noexcept
12744 {
12745 return m_it;
12746 }
12747
12749 void set_begin() noexcept
12750 {
12751 m_it = begin_value;
12752 }
12753
12755 void set_end() noexcept
12756 {
12757 m_it = end_value;
12758 }
12759
12761 constexpr bool is_begin() const noexcept
12762 {
12763 return m_it == begin_value;
12764 }
12765
12767 constexpr bool is_end() const noexcept
12768 {
12769 return m_it == end_value;
12770 }
12771
12772 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12773 {
12774 return lhs.m_it == rhs.m_it;
12775 }
12776
12777 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12778 {
12779 return lhs.m_it < rhs.m_it;
12780 }
12781
12782 primitive_iterator_t operator+(difference_type n) noexcept
12783 {
12784 auto result = *this;
12785 result += n;
12786 return result;
12787 }
12788
12789 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12790 {
12791 return lhs.m_it - rhs.m_it;
12792 }
12793
12795 {
12796 ++m_it;
12797 return *this;
12798 }
12799
12800 primitive_iterator_t operator++(int)&noexcept // NOLINT(cert-dcl21-cpp)
12801 {
12802 auto result = *this;
12803 ++m_it;
12804 return result;
12805 }
12806
12808 {
12809 --m_it;
12810 return *this;
12811 }
12812
12813 primitive_iterator_t operator--(int)&noexcept // NOLINT(cert-dcl21-cpp)
12814 {
12815 auto result = *this;
12816 --m_it;
12817 return result;
12818 }
12819
12820 primitive_iterator_t& operator+=(difference_type n) noexcept
12821 {
12822 m_it += n;
12823 return *this;
12824 }
12825
12826 primitive_iterator_t& operator-=(difference_type n) noexcept
12827 {
12828 m_it -= n;
12829 return *this;
12830 }
12831 };
12832
12833} // namespace detail
12835
12836
12838namespace detail
12839{
12840
12847 template<typename BasicJsonType> struct internal_iterator
12848 {
12850 typename BasicJsonType::object_t::iterator object_iterator{};
12852 typename BasicJsonType::array_t::iterator array_iterator{};
12855 };
12856
12857} // namespace detail
12859
12860// #include <nlohmann/detail/iterators/iter_impl.hpp>
12861// __ _____ _____ _____
12862// __| | __| | | | JSON for Modern C++
12863// | | |__ | | | | | | version 3.11.3
12864// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12865//
12866// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12867// SPDX-License-Identifier: MIT
12868
12869
12870
12871#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12872#include <type_traits> // conditional, is_const, remove_const
12873
12874// #include <nlohmann/detail/exceptions.hpp>
12875
12876// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12877
12878// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12879
12880// #include <nlohmann/detail/macro_scope.hpp>
12881
12882// #include <nlohmann/detail/meta/cpp_future.hpp>
12883
12884// #include <nlohmann/detail/meta/type_traits.hpp>
12885
12886// #include <nlohmann/detail/value_t.hpp>
12887
12888
12890namespace detail
12891{
12892
12893 // forward declare, to be able to friend it later on
12894 template<typename IteratorType> class iteration_proxy;
12895 template<typename IteratorType> class iteration_proxy_value;
12896
12913 template<typename BasicJsonType>
12914 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12915 {
12917 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12919 friend other_iter_impl;
12920 friend BasicJsonType;
12923
12924 using object_t = typename BasicJsonType::object_t;
12925 using array_t = typename BasicJsonType::array_t;
12926 // make sure BasicJsonType is basic_json or const basic_json
12928 "iter_impl only accepts (const) basic_json");
12929 // superficial check for the LegacyBidirectionalIterator named requirement
12930 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12931 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12932 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12933
12934 public:
12940 using iterator_category = std::bidirectional_iterator_tag;
12941
12943 using value_type = typename BasicJsonType::value_type;
12945 using difference_type = typename BasicJsonType::difference_type;
12947 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12948 typename BasicJsonType::const_pointer,
12949 typename BasicJsonType::pointer>::type;
12952 typename std::conditional<std::is_const<BasicJsonType>::value,
12953 typename BasicJsonType::const_reference,
12954 typename BasicJsonType::reference>::type;
12955
12956 iter_impl() = default;
12957 ~iter_impl() = default;
12958 iter_impl(iter_impl&&) noexcept = default;
12959 iter_impl& operator=(iter_impl&&) noexcept = default;
12960
12967 explicit iter_impl(pointer object) noexcept : m_object(object)
12968 {
12969 JSON_ASSERT(m_object != nullptr);
12970
12971 switch (m_object->m_data.m_type)
12972 {
12973 case value_t::object:
12974 {
12975 m_it.object_iterator = typename object_t::iterator();
12976 break;
12977 }
12978
12979 case value_t::array:
12980 {
12981 m_it.array_iterator = typename array_t::iterator();
12982 break;
12983 }
12984
12985 case value_t::null:
12986 case value_t::string:
12987 case value_t::boolean:
12991 case value_t::binary:
12992 case value_t::discarded:
12993 default:
12994 {
12995 m_it.primitive_iterator = primitive_iterator_t();
12996 break;
12997 }
12998 }
12999 }
13000
13018 : m_object(other.m_object), m_it(other.m_it)
13019 {}
13020
13028 {
13029 if (&other != this)
13030 {
13031 m_object = other.m_object;
13032 m_it = other.m_it;
13033 }
13034 return *this;
13035 }
13036
13042 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13043 : m_object(other.m_object), m_it(other.m_it)
13044 {}
13045
13052 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13053 {
13054 m_object = other.m_object;
13055 m_it = other.m_it;
13056 return *this;
13057 }
13058
13064 void set_begin() noexcept
13065 {
13066 JSON_ASSERT(m_object != nullptr);
13067
13068 switch (m_object->m_data.m_type)
13069 {
13070 case value_t::object:
13071 {
13072 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13073 break;
13074 }
13075
13076 case value_t::array:
13077 {
13078 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13079 break;
13080 }
13081
13082 case value_t::null:
13083 {
13084 // set to end so begin()==end() is true: null is empty
13085 m_it.primitive_iterator.set_end();
13086 break;
13087 }
13088
13089 case value_t::string:
13090 case value_t::boolean:
13094 case value_t::binary:
13095 case value_t::discarded:
13096 default:
13097 {
13098 m_it.primitive_iterator.set_begin();
13099 break;
13100 }
13101 }
13102 }
13103
13108 void set_end() noexcept
13109 {
13110 JSON_ASSERT(m_object != nullptr);
13111
13112 switch (m_object->m_data.m_type)
13113 {
13114 case value_t::object:
13115 {
13116 m_it.object_iterator = m_object->m_data.m_value.object->end();
13117 break;
13118 }
13119
13120 case value_t::array:
13121 {
13122 m_it.array_iterator = m_object->m_data.m_value.array->end();
13123 break;
13124 }
13125
13126 case value_t::null:
13127 case value_t::string:
13128 case value_t::boolean:
13132 case value_t::binary:
13133 case value_t::discarded:
13134 default:
13135 {
13136 m_it.primitive_iterator.set_end();
13137 break;
13138 }
13139 }
13140 }
13141
13142 public:
13148 {
13149 JSON_ASSERT(m_object != nullptr);
13150
13151 switch (m_object->m_data.m_type)
13152 {
13153 case value_t::object:
13154 {
13155 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13156 return m_it.object_iterator->second;
13157 }
13158
13159 case value_t::array:
13160 {
13161 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13162 return *m_it.array_iterator;
13163 }
13164
13165 case value_t::null:
13166 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13167
13168 case value_t::string:
13169 case value_t::boolean:
13173 case value_t::binary:
13174 case value_t::discarded:
13175 default:
13176 {
13177 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13178 {
13179 return *m_object;
13180 }
13181
13182 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13183 }
13184 }
13185 }
13186
13192 {
13193 JSON_ASSERT(m_object != nullptr);
13194
13195 switch (m_object->m_data.m_type)
13196 {
13197 case value_t::object:
13198 {
13199 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13200 return &(m_it.object_iterator->second);
13201 }
13202
13203 case value_t::array:
13204 {
13205 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13206 return &*m_it.array_iterator;
13207 }
13208
13209 case value_t::null:
13210 case value_t::string:
13211 case value_t::boolean:
13215 case value_t::binary:
13216 case value_t::discarded:
13217 default:
13218 {
13219 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13220 {
13221 return m_object;
13222 }
13223
13224 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13225 }
13226 }
13227 }
13228
13233 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13234 {
13235 auto result = *this;
13236 ++(*this);
13237 return result;
13238 }
13239
13245 {
13246 JSON_ASSERT(m_object != nullptr);
13247
13248 switch (m_object->m_data.m_type)
13249 {
13250 case value_t::object:
13251 {
13252 std::advance(m_it.object_iterator, 1);
13253 break;
13254 }
13255
13256 case value_t::array:
13257 {
13258 std::advance(m_it.array_iterator, 1);
13259 break;
13260 }
13261
13262 case value_t::null:
13263 case value_t::string:
13264 case value_t::boolean:
13268 case value_t::binary:
13269 case value_t::discarded:
13270 default:
13271 {
13272 ++m_it.primitive_iterator;
13273 break;
13274 }
13275 }
13276
13277 return *this;
13278 }
13279
13284 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13285 {
13286 auto result = *this;
13287 --(*this);
13288 return result;
13289 }
13290
13296 {
13297 JSON_ASSERT(m_object != nullptr);
13298
13299 switch (m_object->m_data.m_type)
13300 {
13301 case value_t::object:
13302 {
13303 std::advance(m_it.object_iterator, -1);
13304 break;
13305 }
13306
13307 case value_t::array:
13308 {
13309 std::advance(m_it.array_iterator, -1);
13310 break;
13311 }
13312
13313 case value_t::null:
13314 case value_t::string:
13315 case value_t::boolean:
13319 case value_t::binary:
13320 case value_t::discarded:
13321 default:
13322 {
13323 --m_it.primitive_iterator;
13324 break;
13325 }
13326 }
13327
13328 return *this;
13329 }
13330
13335 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13336 bool operator==(const IterImpl& other) const
13337 {
13338 // if objects are not the same, the comparison is undefined
13339 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13340 {
13341 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13342 }
13343
13344 JSON_ASSERT(m_object != nullptr);
13345
13346 switch (m_object->m_data.m_type)
13347 {
13348 case value_t::object:
13349 return (m_it.object_iterator == other.m_it.object_iterator);
13350
13351 case value_t::array:
13352 return (m_it.array_iterator == other.m_it.array_iterator);
13353
13354 case value_t::null:
13355 case value_t::string:
13356 case value_t::boolean:
13360 case value_t::binary:
13361 case value_t::discarded:
13362 default:
13363 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13364 }
13365 }
13366
13371 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
13372 bool operator!=(const IterImpl& other) const
13373 {
13374 return !operator==(other);
13375 }
13376
13381 bool operator<(const iter_impl& other) const
13382 {
13383 // if objects are not the same, the comparison is undefined
13384 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13385 {
13386 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13387 }
13388
13389 JSON_ASSERT(m_object != nullptr);
13390
13391 switch (m_object->m_data.m_type)
13392 {
13393 case value_t::object:
13394 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13395
13396 case value_t::array:
13397 return (m_it.array_iterator < other.m_it.array_iterator);
13398
13399 case value_t::null:
13400 case value_t::string:
13401 case value_t::boolean:
13405 case value_t::binary:
13406 case value_t::discarded:
13407 default:
13408 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13409 }
13410 }
13411
13416 bool operator<=(const iter_impl& other) const
13417 {
13418 return !other.operator < (*this);
13419 }
13420
13425 bool operator>(const iter_impl& other) const
13426 {
13427 return !operator<=(other);
13428 }
13429
13434 bool operator>=(const iter_impl& other) const
13435 {
13436 return !operator<(other);
13437 }
13438
13444 {
13445 JSON_ASSERT(m_object != nullptr);
13446
13447 switch (m_object->m_data.m_type)
13448 {
13449 case value_t::object:
13450 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13451
13452 case value_t::array:
13453 {
13454 std::advance(m_it.array_iterator, i);
13455 break;
13456 }
13457
13458 case value_t::null:
13459 case value_t::string:
13460 case value_t::boolean:
13464 case value_t::binary:
13465 case value_t::discarded:
13466 default:
13467 {
13468 m_it.primitive_iterator += i;
13469 break;
13470 }
13471 }
13472
13473 return *this;
13474 }
13475
13481 {
13482 return operator+=(-i);
13483 }
13484
13490 {
13491 auto result = *this;
13492 result += i;
13493 return result;
13494 }
13495
13501 {
13502 auto result = it;
13503 result += i;
13504 return result;
13505 }
13506
13512 {
13513 auto result = *this;
13514 result -= i;
13515 return result;
13516 }
13517
13523 {
13524 JSON_ASSERT(m_object != nullptr);
13525
13526 switch (m_object->m_data.m_type)
13527 {
13528 case value_t::object:
13529 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13530
13531 case value_t::array:
13532 return m_it.array_iterator - other.m_it.array_iterator;
13533
13534 case value_t::null:
13535 case value_t::string:
13536 case value_t::boolean:
13540 case value_t::binary:
13541 case value_t::discarded:
13542 default:
13543 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13544 }
13545 }
13546
13552 {
13553 JSON_ASSERT(m_object != nullptr);
13554
13555 switch (m_object->m_data.m_type)
13556 {
13557 case value_t::object:
13558 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13559
13560 case value_t::array:
13561 return *std::next(m_it.array_iterator, n);
13562
13563 case value_t::null:
13564 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13565
13566 case value_t::string:
13567 case value_t::boolean:
13571 case value_t::binary:
13572 case value_t::discarded:
13573 default:
13574 {
13575 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13576 {
13577 return *m_object;
13578 }
13579
13580 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13581 }
13582 }
13583 }
13584
13589 const typename object_t::key_type& key() const
13590 {
13591 JSON_ASSERT(m_object != nullptr);
13592
13593 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13594 {
13595 return m_it.object_iterator->first;
13596 }
13597
13598 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13599 }
13600
13606 {
13607 return operator*();
13608 }
13609
13612 pointer m_object = nullptr;
13615 };
13616
13617} // namespace detail
13619
13620// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13621
13622// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13623// __ _____ _____ _____
13624// __| | __| | | | JSON for Modern C++
13625// | | |__ | | | | | | version 3.11.3
13626// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13627//
13628// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13629// SPDX-License-Identifier: MIT
13630
13631
13632
13633#include <cstddef> // ptrdiff_t
13634#include <iterator> // reverse_iterator
13635#include <utility> // declval
13636
13637// #include <nlohmann/detail/abi_macros.hpp>
13638
13639
13641namespace detail
13642{
13643
13645 // reverse_iterator //
13647
13666 template<typename Base>
13667 class json_reverse_iterator : public std::reverse_iterator<Base>
13668 {
13669 public:
13670 using difference_type = std::ptrdiff_t;
13672 using base_iterator = std::reverse_iterator<Base>;
13674 using reference = typename Base::reference;
13675
13677 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13678 : base_iterator(it) {}
13679
13681 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13682
13684 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13685 {
13686 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13687 }
13688
13691 {
13692 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13693 }
13694
13696 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13697 {
13698 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13699 }
13700
13703 {
13704 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13705 }
13706
13709 {
13710 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13711 }
13712
13715 {
13716 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13717 }
13718
13721 {
13722 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13723 }
13724
13727 {
13728 return base_iterator(*this) - base_iterator(other);
13729 }
13730
13733 {
13734 return *(this->operator+(n));
13735 }
13736
13738 auto key() const -> decltype(std::declval<Base>().key())
13739 {
13740 auto it = --this->base();
13741 return it.key();
13742 }
13743
13746 {
13747 auto it = --this->base();
13748 return it.operator * ();
13749 }
13750 };
13751
13752} // namespace detail
13754
13755// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13756
13757// #include <nlohmann/detail/json_custom_base_class.hpp>
13758// __ _____ _____ _____
13759// __| | __| | | | JSON for Modern C++
13760// | | |__ | | | | | | version 3.11.3
13761// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13762//
13763// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13764// SPDX-License-Identifier: MIT
13765
13766
13767
13768#include <type_traits> // conditional, is_same
13769
13770// #include <nlohmann/detail/abi_macros.hpp>
13771
13772
13774namespace detail
13775{
13776
13788
13789 template<class T>
13790 using json_base_class = typename std::conditional <
13791 std::is_same<T, void>::value,
13793 T
13794 >::type;
13795
13796} // namespace detail
13798
13799// #include <nlohmann/detail/json_pointer.hpp>
13800// __ _____ _____ _____
13801// __| | __| | | | JSON for Modern C++
13802// | | |__ | | | | | | version 3.11.3
13803// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13804//
13805// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13806// SPDX-License-Identifier: MIT
13807
13808
13809
13810#include <algorithm> // all_of
13811#include <cctype> // isdigit
13812#include <cerrno> // errno, ERANGE
13813#include <cstdlib> // strtoull
13814#ifndef JSON_NO_IO
13815#include <iosfwd> // ostream
13816#endif // JSON_NO_IO
13817#include <limits> // max
13818#include <numeric> // accumulate
13819#include <string> // string
13820#include <utility> // move
13821#include <vector> // vector
13822
13823// #include <nlohmann/detail/exceptions.hpp>
13824
13825// #include <nlohmann/detail/macro_scope.hpp>
13826
13827// #include <nlohmann/detail/string_concat.hpp>
13828
13829// #include <nlohmann/detail/string_escape.hpp>
13830
13831// #include <nlohmann/detail/value_t.hpp>
13832
13833
13835
13838template<typename RefStringType>
13840{
13841 // allow basic_json to access private members
13843 friend class basic_json;
13844
13845 template<typename>
13846 friend class json_pointer;
13847
13848 template<typename T>
13849 struct string_t_helper
13850 {
13851 using type = T;
13852 };
13853
13855 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13856 {
13857 using type = StringType;
13858 };
13859
13860public:
13861 // for backwards compatibility accept BasicJsonType
13862 using string_t = typename string_t_helper<RefStringType>::type;
13863
13866 explicit json_pointer(const string_t& s = "")
13867 : reference_tokens(split(s))
13868 {}
13869
13873 {
13874 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13875 string_t{},
13876 [](const string_t& a, const string_t& b)
13877 {
13878 return detail::concat(a, '/', detail::escape(b));
13879 });
13880 }
13881
13885 operator string_t() const
13886 {
13887 return to_string();
13888 }
13889
13890#ifndef JSON_NO_IO
13893 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13894 {
13895 o << ptr.to_string();
13896 return o;
13897 }
13898#endif
13899
13903 {
13904 reference_tokens.insert(reference_tokens.end(),
13905 ptr.reference_tokens.begin(),
13906 ptr.reference_tokens.end());
13907 return *this;
13908 }
13909
13913 {
13914 push_back(std::move(token));
13915 return *this;
13916 }
13917
13920 json_pointer& operator/=(std::size_t array_idx)
13921 {
13922 return *this /= std::to_string(array_idx);
13923 }
13924
13928 const json_pointer& rhs)
13929 {
13930 return json_pointer(lhs) /= rhs;
13931 }
13932
13935 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13936 {
13937 return json_pointer(lhs) /= std::move(token);
13938 }
13939
13942 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13943 {
13944 return json_pointer(lhs) /= array_idx;
13945 }
13946
13950 {
13951 if (empty())
13952 {
13953 return *this;
13954 }
13955
13956 json_pointer res = *this;
13957 res.pop_back();
13958 return res;
13959 }
13960
13964 {
13966 {
13967 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13968 }
13969
13970 reference_tokens.pop_back();
13971 }
13972
13975 const string_t& back() const
13976 {
13978 {
13979 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13980 }
13981
13982 return reference_tokens.back();
13983 }
13984
13987 void push_back(const string_t& token)
13988 {
13989 reference_tokens.push_back(token);
13990 }
13991
13994 void push_back(string_t&& token)
13995 {
13996 reference_tokens.push_back(std::move(token));
13997 }
13998
14001 bool empty() const noexcept
14002 {
14003 return reference_tokens.empty();
14004 }
14005
14006private:
14017 template<typename BasicJsonType>
14018 static typename BasicJsonType::size_type array_index(const string_t& s)
14019 {
14020 using size_type = typename BasicJsonType::size_type;
14021
14022 // error condition (cf. RFC 6901, Sect. 4)
14023 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14024 {
14025 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14026 }
14027
14028 // error condition (cf. RFC 6901, Sect. 4)
14029 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14030 {
14031 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14032 }
14033
14034 const char* p = s.c_str();
14035 char* p_end = nullptr;
14036 errno = 0; // strtoull doesn't reset errno
14037 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14038 if (p == p_end // invalid input or empty string
14039 || errno == ERANGE // out of range
14040 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14041 {
14042 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14043 }
14044
14045 // only triggered on special platforms (like 32bit), see also
14046 // https://github.com/nlohmann/json/pull/2203
14047 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14048 {
14049 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14050 }
14051
14052 return static_cast<size_type>(res);
14053 }
14054
14056 json_pointer top() const
14057 {
14059 {
14060 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14061 }
14062
14063 json_pointer result = *this;
14064 result.reference_tokens = { reference_tokens[0] };
14065 return result;
14066 }
14067
14068private:
14077 template<typename BasicJsonType>
14078 BasicJsonType& get_and_create(BasicJsonType& j) const
14079 {
14080 auto* result = &j;
14081
14082 // in case no reference tokens exist, return a reference to the JSON value
14083 // j which will be overwritten by a primitive value
14084 for (const auto& reference_token : reference_tokens)
14085 {
14086 switch (result->type())
14087 {
14089 {
14090 if (reference_token == "0")
14091 {
14092 // start a new array if reference token is 0
14093 result = &result->operator[](0);
14094 }
14095 else
14096 {
14097 // start a new object otherwise
14098 result = &result->operator[](reference_token);
14099 }
14100 break;
14101 }
14102
14104 {
14105 // create an entry in the object
14106 result = &result->operator[](reference_token);
14107 break;
14108 }
14109
14111 {
14112 // create an entry in the array
14113 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14114 break;
14115 }
14116
14117 /*
14118 The following code is only reached if there exists a reference
14119 token _and_ the current value is primitive. In this case, we have
14120 an error situation, because primitive values may only occur as
14121 single value; that is, with an empty list of reference tokens.
14122 */
14130 default:
14131 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14132 }
14133 }
14134
14135 return *result;
14136 }
14137
14157 template<typename BasicJsonType>
14158 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14159 {
14160 for (const auto& reference_token : reference_tokens)
14161 {
14162 // convert null values to arrays or objects before continuing
14163 if (ptr->is_null())
14164 {
14165 // check if reference token is a number
14166 const bool nums =
14167 std::all_of(reference_token.begin(), reference_token.end(),
14168 [](const unsigned char x)
14169 {
14170 return std::isdigit(x);
14171 });
14172
14173 // change value to array for numbers or "-" or to object otherwise
14174 *ptr = (nums || reference_token == "-")
14176 : detail::value_t::object;
14177 }
14178
14179 switch (ptr->type())
14180 {
14182 {
14183 // use unchecked object access
14184 ptr = &ptr->operator[](reference_token);
14185 break;
14186 }
14187
14189 {
14190 if (reference_token == "-")
14191 {
14192 // explicitly treat "-" as index beyond the end
14193 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14194 }
14195 else
14196 {
14197 // convert array index to number; unchecked access
14198 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14199 }
14200 break;
14201 }
14202
14211 default:
14212 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14213 }
14214 }
14215
14216 return *ptr;
14217 }
14218
14225 template<typename BasicJsonType>
14226 BasicJsonType& get_checked(BasicJsonType* ptr) const
14227 {
14228 for (const auto& reference_token : reference_tokens)
14229 {
14230 switch (ptr->type())
14231 {
14233 {
14234 // note: at performs range check
14235 ptr = &ptr->at(reference_token);
14236 break;
14237 }
14238
14240 {
14241 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14242 {
14243 // "-" always fails the range check
14245 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14246 ") is out of range"), ptr));
14247 }
14248
14249 // note: at performs range check
14250 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14251 break;
14252 }
14253
14262 default:
14263 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14264 }
14265 }
14266
14267 return *ptr;
14268 }
14269
14283 template<typename BasicJsonType>
14284 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14285 {
14286 for (const auto& reference_token : reference_tokens)
14287 {
14288 switch (ptr->type())
14289 {
14291 {
14292 // use unchecked object access
14293 ptr = &ptr->operator[](reference_token);
14294 break;
14295 }
14296
14298 {
14299 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14300 {
14301 // "-" cannot be used for const access
14302 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
14303 }
14304
14305 // use unchecked array access
14306 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14307 break;
14308 }
14309
14318 default:
14319 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14320 }
14321 }
14322
14323 return *ptr;
14324 }
14325
14332 template<typename BasicJsonType>
14333 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14334 {
14335 for (const auto& reference_token : reference_tokens)
14336 {
14337 switch (ptr->type())
14338 {
14340 {
14341 // note: at performs range check
14342 ptr = &ptr->at(reference_token);
14343 break;
14344 }
14345
14347 {
14348 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14349 {
14350 // "-" always fails the range check
14352 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14353 ") is out of range"), ptr));
14354 }
14355
14356 // note: at performs range check
14357 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14358 break;
14359 }
14360
14369 default:
14370 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14371 }
14372 }
14373
14374 return *ptr;
14375 }
14376
14381 template<typename BasicJsonType>
14382 bool contains(const BasicJsonType* ptr) const
14383 {
14384 for (const auto& reference_token : reference_tokens)
14385 {
14386 switch (ptr->type())
14387 {
14389 {
14390 if (!ptr->contains(reference_token))
14391 {
14392 // we did not find the key in the object
14393 return false;
14394 }
14395
14396 ptr = &ptr->operator[](reference_token);
14397 break;
14398 }
14399
14401 {
14402 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14403 {
14404 // "-" always fails the range check
14405 return false;
14406 }
14407 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14408 {
14409 // invalid char
14410 return false;
14411 }
14412 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14413 {
14414 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14415 {
14416 // first char should be between '1' and '9'
14417 return false;
14418 }
14419 for (std::size_t i = 1; i < reference_token.size(); i++)
14420 {
14421 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14422 {
14423 // other char should be between '0' and '9'
14424 return false;
14425 }
14426 }
14427 }
14428
14429 const auto idx = array_index<BasicJsonType>(reference_token);
14430 if (idx >= ptr->size())
14431 {
14432 // index out of range
14433 return false;
14434 }
14435
14436 ptr = &ptr->operator[](idx);
14437 break;
14438 }
14439
14448 default:
14449 {
14450 // we do not expect primitive values if there is still a
14451 // reference token to process
14452 return false;
14453 }
14454 }
14455 }
14456
14457 // no reference token left means we found a primitive value
14458 return true;
14459 }
14460
14470 static std::vector<string_t> split(const string_t& reference_string)
14471 {
14472 std::vector<string_t> result;
14473
14474 // special case: empty reference string -> no reference tokens
14475 if (reference_string.empty())
14476 {
14477 return result;
14478 }
14479
14480 // check if nonempty reference string begins with slash
14481 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14482 {
14483 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14484 }
14485
14486 // extract the reference tokens:
14487 // - slash: position of the last read slash (or end of string)
14488 // - start: position after the previous slash
14489 for (
14490 // search for the first slash after the first character
14491 std::size_t slash = reference_string.find_first_of('/', 1),
14492 // set the beginning of the first reference token
14493 start = 1;
14494 // we can stop if start == 0 (if slash == string_t::npos)
14495 start != 0;
14496 // set the beginning of the next reference token
14497 // (will eventually be 0 if slash == string_t::npos)
14498 start = (slash == string_t::npos) ? 0 : slash + 1,
14499 // find next slash
14500 slash = reference_string.find_first_of('/', start))
14501 {
14502 // use the text between the beginning of the reference token
14503 // (start) and the last slash (slash).
14504 auto reference_token = reference_string.substr(start, slash - start);
14505
14506 // check reference tokens are properly escaped
14507 for (std::size_t pos = reference_token.find_first_of('~');
14508 pos != string_t::npos;
14509 pos = reference_token.find_first_of('~', pos + 1))
14510 {
14511 JSON_ASSERT(reference_token[pos] == '~');
14512
14513 // ~ must be followed by 0 or 1
14514 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14515 (reference_token[pos + 1] != '0' &&
14516 reference_token[pos + 1] != '1')))
14517 {
14518 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14519 }
14520 }
14521
14522 // finally, store the reference token
14523 detail::unescape(reference_token);
14524 result.push_back(reference_token);
14525 }
14526
14527 return result;
14528 }
14529
14530private:
14538 template<typename BasicJsonType>
14539 static void flatten(const string_t& reference_string,
14540 const BasicJsonType& value,
14541 BasicJsonType& result)
14542 {
14543 switch (value.type())
14544 {
14546 {
14547 if (value.m_data.m_value.array->empty())
14548 {
14549 // flatten empty array as null
14550 result[reference_string] = nullptr;
14551 }
14552 else
14553 {
14554 // iterate array and use index as reference string
14555 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14556 {
14557 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14558 value.m_data.m_value.array->operator[](i), result);
14559 }
14560 }
14561 break;
14562 }
14563
14565 {
14566 if (value.m_data.m_value.object->empty())
14567 {
14568 // flatten empty object as null
14569 result[reference_string] = nullptr;
14570 }
14571 else
14572 {
14573 // iterate object and use keys as reference string
14574 for (const auto& element : *value.m_data.m_value.object)
14575 {
14576 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14577 }
14578 }
14579 break;
14580 }
14581
14590 default:
14591 {
14592 // add primitive value with its reference string
14593 result[reference_string] = value;
14594 break;
14595 }
14596 }
14597 }
14598
14609 template<typename BasicJsonType>
14610 static BasicJsonType
14611 unflatten(const BasicJsonType& value)
14612 {
14613 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14614 {
14615 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14616 }
14617
14618 BasicJsonType result;
14619
14620 // iterate the JSON object values
14621 for (const auto& element : *value.m_data.m_value.object)
14622 {
14623 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14624 {
14625 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14626 }
14627
14628 // assign value to reference pointed to by JSON pointer; Note that if
14629 // the JSON pointer is "" (i.e., points to the whole value), function
14630 // get_and_create returns a reference to result itself. An assignment
14631 // will then create a primitive value.
14632 json_pointer(element.first).get_and_create(result) = element.second;
14633 }
14634
14635 return result;
14636 }
14637
14638 // can't use conversion operator because of ambiguity
14639 json_pointer<string_t> convert() const&
14640 {
14642 result.reference_tokens = reference_tokens;
14643 return result;
14644 }
14645
14646 json_pointer<string_t> convert()&&
14647 {
14649 result.reference_tokens = std::move(reference_tokens);
14650 return result;
14651 }
14652
14653public:
14654#if JSON_HAS_THREE_WAY_COMPARISON
14657 template<typename RefStringTypeRhs>
14658 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14659 {
14660 return reference_tokens == rhs.reference_tokens;
14661 }
14662
14665 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14666 bool operator==(const string_t& rhs) const
14667 {
14668 return *this == json_pointer(rhs);
14669 }
14670
14672 template<typename RefStringTypeRhs>
14673 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14674 {
14675 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14676 }
14677#else
14680 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14681 // NOLINTNEXTLINE(readability-redundant-declaration)
14682 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14683 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14684
14687 template<typename RefStringTypeLhs, typename StringType>
14688 // NOLINTNEXTLINE(readability-redundant-declaration)
14689 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14690 const StringType& rhs);
14691
14694 template<typename RefStringTypeRhs, typename StringType>
14695 // NOLINTNEXTLINE(readability-redundant-declaration)
14696 friend bool operator==(const StringType& lhs,
14698
14701 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14702 // NOLINTNEXTLINE(readability-redundant-declaration)
14703 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14704 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14705
14708 template<typename RefStringTypeLhs, typename StringType>
14709 // NOLINTNEXTLINE(readability-redundant-declaration)
14710 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14711 const StringType& rhs);
14712
14715 template<typename RefStringTypeRhs, typename StringType>
14716 // NOLINTNEXTLINE(readability-redundant-declaration)
14717 friend bool operator!=(const StringType& lhs,
14719
14721 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14722 // NOLINTNEXTLINE(readability-redundant-declaration)
14723 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14724 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14725#endif
14726
14727private:
14729 std::vector<string_t> reference_tokens;
14730};
14731
14732#if !JSON_HAS_THREE_WAY_COMPARISON
14733// functions cannot be defined inside class due to ODR violations
14734template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14736 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14737{
14738 return lhs.reference_tokens == rhs.reference_tokens;
14739}
14740
14741template<typename RefStringTypeLhs,
14742 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14744inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14745 const StringType& rhs)
14746{
14747 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14748}
14749
14750template<typename RefStringTypeRhs,
14751 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14753inline bool operator==(const StringType& lhs,
14754 const json_pointer<RefStringTypeRhs>& rhs)
14755{
14756 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14757}
14758
14759template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14761 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14762{
14763 return !(lhs == rhs);
14764}
14765
14766template<typename RefStringTypeLhs,
14767 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14769inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14770 const StringType& rhs)
14771{
14772 return !(lhs == rhs);
14773}
14774
14775template<typename RefStringTypeRhs,
14776 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14778inline bool operator!=(const StringType& lhs,
14779 const json_pointer<RefStringTypeRhs>& rhs)
14780{
14781 return !(lhs == rhs);
14782}
14783
14784template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14786 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14787{
14788 return lhs.reference_tokens < rhs.reference_tokens;
14789}
14790#endif
14791
14793
14794// #include <nlohmann/detail/json_ref.hpp>
14795// __ _____ _____ _____
14796// __| | __| | | | JSON for Modern C++
14797// | | |__ | | | | | | version 3.11.3
14798// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14799//
14800// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14801// SPDX-License-Identifier: MIT
14802
14803
14804
14805#include <initializer_list>
14806#include <utility>
14807
14808// #include <nlohmann/detail/abi_macros.hpp>
14809
14810// #include <nlohmann/detail/meta/type_traits.hpp>
14811
14812
14814namespace detail
14815{
14816
14817 template<typename BasicJsonType>
14819 {
14820 public:
14821 using value_type = BasicJsonType;
14822
14824 : owned_value(std::move(value))
14825 {}
14826
14828 : value_ref(&value)
14829 {}
14830
14831 json_ref(std::initializer_list<json_ref> init)
14832 : owned_value(init)
14833 {}
14834
14835 template <
14836 class... Args,
14837 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14838 json_ref(Args && ... args)
14839 : owned_value(std::forward<Args>(args)...)
14840 {}
14841
14842 // class should be movable only
14843 json_ref(json_ref&&) noexcept = default;
14844 json_ref(const json_ref&) = delete;
14845 json_ref& operator=(const json_ref&) = delete;
14846 json_ref& operator=(json_ref&&) = delete;
14847 ~json_ref() = default;
14848
14850 {
14851 if (value_ref == nullptr)
14852 {
14853 return std::move(owned_value);
14854 }
14855 return *value_ref;
14856 }
14857
14858 value_type const& operator*() const
14859 {
14860 return value_ref ? *value_ref : owned_value;
14861 }
14862
14863 value_type const* operator->() const
14864 {
14865 return &**this;
14866 }
14867
14868 private:
14869 mutable value_type owned_value = nullptr;
14870 value_type const* value_ref = nullptr;
14871 };
14872
14873} // namespace detail
14875
14876// #include <nlohmann/detail/macro_scope.hpp>
14877
14878// #include <nlohmann/detail/string_concat.hpp>
14879
14880// #include <nlohmann/detail/string_escape.hpp>
14881
14882// #include <nlohmann/detail/meta/cpp_future.hpp>
14883
14884// #include <nlohmann/detail/meta/type_traits.hpp>
14885
14886// #include <nlohmann/detail/output/binary_writer.hpp>
14887// __ _____ _____ _____
14888// __| | __| | | | JSON for Modern C++
14889// | | |__ | | | | | | version 3.11.3
14890// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14891//
14892// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14893// SPDX-License-Identifier: MIT
14894
14895
14896
14897#include <algorithm> // reverse
14898#include <array> // array
14899#include <map> // map
14900#include <cmath> // isnan, isinf
14901#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14902#include <cstring> // memcpy
14903#include <limits> // numeric_limits
14904#include <string> // string
14905#include <utility> // move
14906#include <vector> // vector
14907
14908// #include <nlohmann/detail/input/binary_reader.hpp>
14909
14910// #include <nlohmann/detail/macro_scope.hpp>
14911
14912// #include <nlohmann/detail/output/output_adapters.hpp>
14913// __ _____ _____ _____
14914// __| | __| | | | JSON for Modern C++
14915// | | |__ | | | | | | version 3.11.3
14916// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14917//
14918// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14919// SPDX-License-Identifier: MIT
14920
14921
14922
14923#include <algorithm> // copy
14924#include <cstddef> // size_t
14925#include <iterator> // back_inserter
14926#include <memory> // shared_ptr, make_shared
14927#include <string> // basic_string
14928#include <vector> // vector
14929
14930#ifndef JSON_NO_IO
14931#include <ios> // streamsize
14932#include <ostream> // basic_ostream
14933#endif // JSON_NO_IO
14934
14935// #include <nlohmann/detail/macro_scope.hpp>
14936
14937
14939namespace detail
14940{
14941
14943 template<typename CharType> struct output_adapter_protocol
14944 {
14945 virtual void write_character(CharType c) = 0;
14946 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14947 virtual ~output_adapter_protocol() = default;
14948
14953 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14954 };
14955
14957 template<typename CharType>
14958 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14959
14961 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14963 {
14964 public:
14965 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14966 : v(vec)
14967 {}
14968
14969 void write_character(CharType c) override
14970 {
14971 v.push_back(c);
14972 }
14973
14975 void write_characters(const CharType* s, std::size_t length) override
14976 {
14977 v.insert(v.end(), s, s + length);
14978 }
14979
14980 private:
14981 std::vector<CharType, AllocatorType>& v;
14982 };
14983
14984#ifndef JSON_NO_IO
14986 template<typename CharType>
14988 {
14989 public:
14990 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
14991 : stream(s)
14992 {}
14993
14994 void write_character(CharType c) override
14995 {
14996 stream.put(c);
14997 }
14998
15000 void write_characters(const CharType* s, std::size_t length) override
15001 {
15002 stream.write(s, static_cast<std::streamsize>(length));
15003 }
15004
15005 private:
15006 std::basic_ostream<CharType>& stream;
15007 };
15008#endif // JSON_NO_IO
15009
15011 template<typename CharType, typename StringType = std::basic_string<CharType>>
15013 {
15014 public:
15015 explicit output_string_adapter(StringType& s) noexcept
15016 : str(s)
15017 {}
15018
15019 void write_character(CharType c) override
15020 {
15021 str.push_back(c);
15022 }
15023
15025 void write_characters(const CharType* s, std::size_t length) override
15026 {
15027 str.append(s, length);
15028 }
15029
15030 private:
15031 StringType& str;
15032 };
15033
15034 template<typename CharType, typename StringType = std::basic_string<CharType>>
15036 {
15037 public:
15038 template<typename AllocatorType = std::allocator<CharType>>
15039 output_adapter(std::vector<CharType, AllocatorType>& vec)
15040 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15041
15042#ifndef JSON_NO_IO
15043 output_adapter(std::basic_ostream<CharType>& s)
15044 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15045#endif // JSON_NO_IO
15046
15047 output_adapter(StringType& s)
15048 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15049
15051 {
15052 return oa;
15053 }
15054
15055 private:
15056 output_adapter_t<CharType> oa = nullptr;
15057 };
15058
15059} // namespace detail
15061
15062// #include <nlohmann/detail/string_concat.hpp>
15063
15064
15066namespace detail
15067{
15068
15070 // binary writer //
15072
15076 template<typename BasicJsonType, typename CharType>
15078 {
15079 using string_t = typename BasicJsonType::string_t;
15080 using binary_t = typename BasicJsonType::binary_t;
15081 using number_float_t = typename BasicJsonType::number_float_t;
15082
15083 public:
15089 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15090 {
15091 JSON_ASSERT(oa);
15092 }
15093
15098 void write_bson(const BasicJsonType& j)
15099 {
15100 switch (j.type())
15101 {
15102 case value_t::object:
15103 {
15104 write_bson_object(*j.m_data.m_value.object);
15105 break;
15106 }
15107
15108 case value_t::null:
15109 case value_t::array:
15110 case value_t::string:
15111 case value_t::boolean:
15112 case value_t::number_integer:
15113 case value_t::number_unsigned:
15114 case value_t::number_float:
15115 case value_t::binary:
15116 case value_t::discarded:
15117 default:
15118 {
15119 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15120 }
15121 }
15122 }
15123
15127 void write_cbor(const BasicJsonType& j)
15128 {
15129 switch (j.type())
15130 {
15131 case value_t::null:
15132 {
15133 oa->write_character(to_char_type(0xF6));
15134 break;
15135 }
15136
15137 case value_t::boolean:
15138 {
15139 oa->write_character(j.m_data.m_value.boolean
15140 ? to_char_type(0xF5)
15141 : to_char_type(0xF4));
15142 break;
15143 }
15144
15145 case value_t::number_integer:
15146 {
15147 if (j.m_data.m_value.number_integer >= 0)
15148 {
15149 // CBOR does not differentiate between positive signed
15150 // integers and unsigned integers. Therefore, we used the
15151 // code from the value_t::number_unsigned case here.
15152 if (j.m_data.m_value.number_integer <= 0x17)
15153 {
15154 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15155 }
15156 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15157 {
15158 oa->write_character(to_char_type(0x18));
15159 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15160 }
15161 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15162 {
15163 oa->write_character(to_char_type(0x19));
15164 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15165 }
15166 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15167 {
15168 oa->write_character(to_char_type(0x1A));
15169 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15170 }
15171 else
15172 {
15173 oa->write_character(to_char_type(0x1B));
15174 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15175 }
15176 }
15177 else
15178 {
15179 // The conversions below encode the sign in the first
15180 // byte, and the value is converted to a positive number.
15181 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15182 if (j.m_data.m_value.number_integer >= -24)
15183 {
15184 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15185 }
15186 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15187 {
15188 oa->write_character(to_char_type(0x38));
15189 write_number(static_cast<std::uint8_t>(positive_number));
15190 }
15191 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15192 {
15193 oa->write_character(to_char_type(0x39));
15194 write_number(static_cast<std::uint16_t>(positive_number));
15195 }
15196 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15197 {
15198 oa->write_character(to_char_type(0x3A));
15199 write_number(static_cast<std::uint32_t>(positive_number));
15200 }
15201 else
15202 {
15203 oa->write_character(to_char_type(0x3B));
15204 write_number(static_cast<std::uint64_t>(positive_number));
15205 }
15206 }
15207 break;
15208 }
15209
15210 case value_t::number_unsigned:
15211 {
15212 if (j.m_data.m_value.number_unsigned <= 0x17)
15213 {
15214 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15215 }
15216 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15217 {
15218 oa->write_character(to_char_type(0x18));
15219 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15220 }
15221 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15222 {
15223 oa->write_character(to_char_type(0x19));
15224 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15225 }
15226 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15227 {
15228 oa->write_character(to_char_type(0x1A));
15229 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15230 }
15231 else
15232 {
15233 oa->write_character(to_char_type(0x1B));
15234 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15235 }
15236 break;
15237 }
15238
15239 case value_t::number_float:
15240 {
15241 if (std::isnan(j.m_data.m_value.number_float))
15242 {
15243 // NaN is 0xf97e00 in CBOR
15244 oa->write_character(to_char_type(0xF9));
15245 oa->write_character(to_char_type(0x7E));
15246 oa->write_character(to_char_type(0x00));
15247 }
15248 else if (std::isinf(j.m_data.m_value.number_float))
15249 {
15250 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15251 oa->write_character(to_char_type(0xf9));
15252 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15253 oa->write_character(to_char_type(0x00));
15254 }
15255 else
15256 {
15257 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15258 }
15259 break;
15260 }
15261
15262 case value_t::string:
15263 {
15264 // step 1: write control byte and the string length
15265 const auto N = j.m_data.m_value.string->size();
15266 if (N <= 0x17)
15267 {
15268 write_number(static_cast<std::uint8_t>(0x60 + N));
15269 }
15270 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15271 {
15272 oa->write_character(to_char_type(0x78));
15273 write_number(static_cast<std::uint8_t>(N));
15274 }
15275 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15276 {
15277 oa->write_character(to_char_type(0x79));
15278 write_number(static_cast<std::uint16_t>(N));
15279 }
15280 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15281 {
15282 oa->write_character(to_char_type(0x7A));
15283 write_number(static_cast<std::uint32_t>(N));
15284 }
15285 // LCOV_EXCL_START
15286 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15287 {
15288 oa->write_character(to_char_type(0x7B));
15289 write_number(static_cast<std::uint64_t>(N));
15290 }
15291 // LCOV_EXCL_STOP
15292
15293 // step 2: write the string
15294 oa->write_characters(
15295 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15296 j.m_data.m_value.string->size());
15297 break;
15298 }
15299
15300 case value_t::array:
15301 {
15302 // step 1: write control byte and the array size
15303 const auto N = j.m_data.m_value.array->size();
15304 if (N <= 0x17)
15305 {
15306 write_number(static_cast<std::uint8_t>(0x80 + N));
15307 }
15308 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15309 {
15310 oa->write_character(to_char_type(0x98));
15311 write_number(static_cast<std::uint8_t>(N));
15312 }
15313 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15314 {
15315 oa->write_character(to_char_type(0x99));
15316 write_number(static_cast<std::uint16_t>(N));
15317 }
15318 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15319 {
15320 oa->write_character(to_char_type(0x9A));
15321 write_number(static_cast<std::uint32_t>(N));
15322 }
15323 // LCOV_EXCL_START
15324 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15325 {
15326 oa->write_character(to_char_type(0x9B));
15327 write_number(static_cast<std::uint64_t>(N));
15328 }
15329 // LCOV_EXCL_STOP
15330
15331 // step 2: write each element
15332 for (const auto& el : *j.m_data.m_value.array)
15333 {
15334 write_cbor(el);
15335 }
15336 break;
15337 }
15338
15339 case value_t::binary:
15340 {
15341 if (j.m_data.m_value.binary->has_subtype())
15342 {
15343 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15344 {
15345 write_number(static_cast<std::uint8_t>(0xd8));
15346 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15347 }
15348 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15349 {
15350 write_number(static_cast<std::uint8_t>(0xd9));
15351 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15352 }
15353 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15354 {
15355 write_number(static_cast<std::uint8_t>(0xda));
15356 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15357 }
15358 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15359 {
15360 write_number(static_cast<std::uint8_t>(0xdb));
15361 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15362 }
15363 }
15364
15365 // step 1: write control byte and the binary array size
15366 const auto N = j.m_data.m_value.binary->size();
15367 if (N <= 0x17)
15368 {
15369 write_number(static_cast<std::uint8_t>(0x40 + N));
15370 }
15371 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15372 {
15373 oa->write_character(to_char_type(0x58));
15374 write_number(static_cast<std::uint8_t>(N));
15375 }
15376 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15377 {
15378 oa->write_character(to_char_type(0x59));
15379 write_number(static_cast<std::uint16_t>(N));
15380 }
15381 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15382 {
15383 oa->write_character(to_char_type(0x5A));
15384 write_number(static_cast<std::uint32_t>(N));
15385 }
15386 // LCOV_EXCL_START
15387 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15388 {
15389 oa->write_character(to_char_type(0x5B));
15390 write_number(static_cast<std::uint64_t>(N));
15391 }
15392 // LCOV_EXCL_STOP
15393
15394 // step 2: write each element
15395 oa->write_characters(
15396 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15397 N);
15398
15399 break;
15400 }
15401
15402 case value_t::object:
15403 {
15404 // step 1: write control byte and the object size
15405 const auto N = j.m_data.m_value.object->size();
15406 if (N <= 0x17)
15407 {
15408 write_number(static_cast<std::uint8_t>(0xA0 + N));
15409 }
15410 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15411 {
15412 oa->write_character(to_char_type(0xB8));
15413 write_number(static_cast<std::uint8_t>(N));
15414 }
15415 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15416 {
15417 oa->write_character(to_char_type(0xB9));
15418 write_number(static_cast<std::uint16_t>(N));
15419 }
15420 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15421 {
15422 oa->write_character(to_char_type(0xBA));
15423 write_number(static_cast<std::uint32_t>(N));
15424 }
15425 // LCOV_EXCL_START
15426 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15427 {
15428 oa->write_character(to_char_type(0xBB));
15429 write_number(static_cast<std::uint64_t>(N));
15430 }
15431 // LCOV_EXCL_STOP
15432
15433 // step 2: write each element
15434 for (const auto& el : *j.m_data.m_value.object)
15435 {
15436 write_cbor(el.first);
15437 write_cbor(el.second);
15438 }
15439 break;
15440 }
15441
15442 case value_t::discarded:
15443 default:
15444 break;
15445 }
15446 }
15447
15451 void write_msgpack(const BasicJsonType& j)
15452 {
15453 switch (j.type())
15454 {
15455 case value_t::null: // nil
15456 {
15457 oa->write_character(to_char_type(0xC0));
15458 break;
15459 }
15460
15461 case value_t::boolean: // true and false
15462 {
15463 oa->write_character(j.m_data.m_value.boolean
15464 ? to_char_type(0xC3)
15465 : to_char_type(0xC2));
15466 break;
15467 }
15468
15469 case value_t::number_integer:
15470 {
15471 if (j.m_data.m_value.number_integer >= 0)
15472 {
15473 // MessagePack does not differentiate between positive
15474 // signed integers and unsigned integers. Therefore, we used
15475 // the code from the value_t::number_unsigned case here.
15476 if (j.m_data.m_value.number_unsigned < 128)
15477 {
15478 // positive fixnum
15479 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15480 }
15481 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15482 {
15483 // uint 8
15484 oa->write_character(to_char_type(0xCC));
15485 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15486 }
15487 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15488 {
15489 // uint 16
15490 oa->write_character(to_char_type(0xCD));
15491 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15492 }
15493 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15494 {
15495 // uint 32
15496 oa->write_character(to_char_type(0xCE));
15497 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15498 }
15499 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15500 {
15501 // uint 64
15502 oa->write_character(to_char_type(0xCF));
15503 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15504 }
15505 }
15506 else
15507 {
15508 if (j.m_data.m_value.number_integer >= -32)
15509 {
15510 // negative fixnum
15511 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15512 }
15513 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15514 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15515 {
15516 // int 8
15517 oa->write_character(to_char_type(0xD0));
15518 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15519 }
15520 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15521 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15522 {
15523 // int 16
15524 oa->write_character(to_char_type(0xD1));
15525 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15526 }
15527 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15528 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15529 {
15530 // int 32
15531 oa->write_character(to_char_type(0xD2));
15532 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15533 }
15534 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15535 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15536 {
15537 // int 64
15538 oa->write_character(to_char_type(0xD3));
15539 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15540 }
15541 }
15542 break;
15543 }
15544
15545 case value_t::number_unsigned:
15546 {
15547 if (j.m_data.m_value.number_unsigned < 128)
15548 {
15549 // positive fixnum
15550 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15551 }
15552 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15553 {
15554 // uint 8
15555 oa->write_character(to_char_type(0xCC));
15556 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15557 }
15558 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15559 {
15560 // uint 16
15561 oa->write_character(to_char_type(0xCD));
15562 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15563 }
15564 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15565 {
15566 // uint 32
15567 oa->write_character(to_char_type(0xCE));
15568 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15569 }
15570 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15571 {
15572 // uint 64
15573 oa->write_character(to_char_type(0xCF));
15574 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15575 }
15576 break;
15577 }
15578
15579 case value_t::number_float:
15580 {
15581 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15582 break;
15583 }
15584
15585 case value_t::string:
15586 {
15587 // step 1: write control byte and the string length
15588 const auto N = j.m_data.m_value.string->size();
15589 if (N <= 31)
15590 {
15591 // fixstr
15592 write_number(static_cast<std::uint8_t>(0xA0 | N));
15593 }
15594 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15595 {
15596 // str 8
15597 oa->write_character(to_char_type(0xD9));
15598 write_number(static_cast<std::uint8_t>(N));
15599 }
15600 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15601 {
15602 // str 16
15603 oa->write_character(to_char_type(0xDA));
15604 write_number(static_cast<std::uint16_t>(N));
15605 }
15606 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15607 {
15608 // str 32
15609 oa->write_character(to_char_type(0xDB));
15610 write_number(static_cast<std::uint32_t>(N));
15611 }
15612
15613 // step 2: write the string
15614 oa->write_characters(
15615 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15616 j.m_data.m_value.string->size());
15617 break;
15618 }
15619
15620 case value_t::array:
15621 {
15622 // step 1: write control byte and the array size
15623 const auto N = j.m_data.m_value.array->size();
15624 if (N <= 15)
15625 {
15626 // fixarray
15627 write_number(static_cast<std::uint8_t>(0x90 | N));
15628 }
15629 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15630 {
15631 // array 16
15632 oa->write_character(to_char_type(0xDC));
15633 write_number(static_cast<std::uint16_t>(N));
15634 }
15635 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15636 {
15637 // array 32
15638 oa->write_character(to_char_type(0xDD));
15639 write_number(static_cast<std::uint32_t>(N));
15640 }
15641
15642 // step 2: write each element
15643 for (const auto& el : *j.m_data.m_value.array)
15644 {
15645 write_msgpack(el);
15646 }
15647 break;
15648 }
15649
15650 case value_t::binary:
15651 {
15652 // step 0: determine if the binary type has a set subtype to
15653 // determine whether or not to use the ext or fixext types
15654 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15655
15656 // step 1: write control byte and the byte string length
15657 const auto N = j.m_data.m_value.binary->size();
15658 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15659 {
15660 std::uint8_t output_type{};
15661 bool fixed = true;
15662 if (use_ext)
15663 {
15664 switch (N)
15665 {
15666 case 1:
15667 output_type = 0xD4; // fixext 1
15668 break;
15669 case 2:
15670 output_type = 0xD5; // fixext 2
15671 break;
15672 case 4:
15673 output_type = 0xD6; // fixext 4
15674 break;
15675 case 8:
15676 output_type = 0xD7; // fixext 8
15677 break;
15678 case 16:
15679 output_type = 0xD8; // fixext 16
15680 break;
15681 default:
15682 output_type = 0xC7; // ext 8
15683 fixed = false;
15684 break;
15685 }
15686
15687 }
15688 else
15689 {
15690 output_type = 0xC4; // bin 8
15691 fixed = false;
15692 }
15693
15694 oa->write_character(to_char_type(output_type));
15695 if (!fixed)
15696 {
15697 write_number(static_cast<std::uint8_t>(N));
15698 }
15699 }
15700 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15701 {
15702 const std::uint8_t output_type = use_ext
15703 ? 0xC8 // ext 16
15704 : 0xC5; // bin 16
15705
15706 oa->write_character(to_char_type(output_type));
15707 write_number(static_cast<std::uint16_t>(N));
15708 }
15709 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15710 {
15711 const std::uint8_t output_type = use_ext
15712 ? 0xC9 // ext 32
15713 : 0xC6; // bin 32
15714
15715 oa->write_character(to_char_type(output_type));
15716 write_number(static_cast<std::uint32_t>(N));
15717 }
15718
15719 // step 1.5: if this is an ext type, write the subtype
15720 if (use_ext)
15721 {
15722 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15723 }
15724
15725 // step 2: write the byte string
15726 oa->write_characters(
15727 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15728 N);
15729
15730 break;
15731 }
15732
15733 case value_t::object:
15734 {
15735 // step 1: write control byte and the object size
15736 const auto N = j.m_data.m_value.object->size();
15737 if (N <= 15)
15738 {
15739 // fixmap
15740 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15741 }
15742 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15743 {
15744 // map 16
15745 oa->write_character(to_char_type(0xDE));
15746 write_number(static_cast<std::uint16_t>(N));
15747 }
15748 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15749 {
15750 // map 32
15751 oa->write_character(to_char_type(0xDF));
15752 write_number(static_cast<std::uint32_t>(N));
15753 }
15754
15755 // step 2: write each element
15756 for (const auto& el : *j.m_data.m_value.object)
15757 {
15758 write_msgpack(el.first);
15759 write_msgpack(el.second);
15760 }
15761 break;
15762 }
15763
15764 case value_t::discarded:
15765 default:
15766 break;
15767 }
15768 }
15769
15777 void write_ubjson(const BasicJsonType& j, const bool use_count,
15778 const bool use_type, const bool add_prefix = true,
15779 const bool use_bjdata = false)
15780 {
15781 switch (j.type())
15782 {
15783 case value_t::null:
15784 {
15785 if (add_prefix)
15786 {
15787 oa->write_character(to_char_type('Z'));
15788 }
15789 break;
15790 }
15791
15792 case value_t::boolean:
15793 {
15794 if (add_prefix)
15795 {
15796 oa->write_character(j.m_data.m_value.boolean
15797 ? to_char_type('T')
15798 : to_char_type('F'));
15799 }
15800 break;
15801 }
15802
15803 case value_t::number_integer:
15804 {
15805 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15806 break;
15807 }
15808
15809 case value_t::number_unsigned:
15810 {
15811 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15812 break;
15813 }
15814
15815 case value_t::number_float:
15816 {
15817 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15818 break;
15819 }
15820
15821 case value_t::string:
15822 {
15823 if (add_prefix)
15824 {
15825 oa->write_character(to_char_type('S'));
15826 }
15827 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15828 oa->write_characters(
15829 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15830 j.m_data.m_value.string->size());
15831 break;
15832 }
15833
15834 case value_t::array:
15835 {
15836 if (add_prefix)
15837 {
15838 oa->write_character(to_char_type('['));
15839 }
15840
15841 bool prefix_required = true;
15842 if (use_type && !j.m_data.m_value.array->empty())
15843 {
15844 JSON_ASSERT(use_count);
15845 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15846 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15847 [this, first_prefix, use_bjdata](const BasicJsonType& v)
15848 {
15849 return ubjson_prefix(v, use_bjdata) == first_prefix;
15850 });
15851
15852 std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
15853
15854 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15855 {
15856 prefix_required = false;
15857 oa->write_character(to_char_type('$'));
15858 oa->write_character(first_prefix);
15859 }
15860 }
15861
15862 if (use_count)
15863 {
15864 oa->write_character(to_char_type('#'));
15865 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15866 }
15867
15868 for (const auto& el : *j.m_data.m_value.array)
15869 {
15870 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15871 }
15872
15873 if (!use_count)
15874 {
15875 oa->write_character(to_char_type(']'));
15876 }
15877
15878 break;
15879 }
15880
15881 case value_t::binary:
15882 {
15883 if (add_prefix)
15884 {
15885 oa->write_character(to_char_type('['));
15886 }
15887
15888 if (use_type && !j.m_data.m_value.binary->empty())
15889 {
15890 JSON_ASSERT(use_count);
15891 oa->write_character(to_char_type('$'));
15892 oa->write_character('U');
15893 }
15894
15895 if (use_count)
15896 {
15897 oa->write_character(to_char_type('#'));
15898 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15899 }
15900
15901 if (use_type)
15902 {
15903 oa->write_characters(
15904 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15905 j.m_data.m_value.binary->size());
15906 }
15907 else
15908 {
15909 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15910 {
15911 oa->write_character(to_char_type('U'));
15912 oa->write_character(j.m_data.m_value.binary->data()[i]);
15913 }
15914 }
15915
15916 if (!use_count)
15917 {
15918 oa->write_character(to_char_type(']'));
15919 }
15920
15921 break;
15922 }
15923
15924 case value_t::object:
15925 {
15926 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
15927 {
15928 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
15929 {
15930 break;
15931 }
15932 }
15933
15934 if (add_prefix)
15935 {
15936 oa->write_character(to_char_type('{'));
15937 }
15938
15939 bool prefix_required = true;
15940 if (use_type && !j.m_data.m_value.object->empty())
15941 {
15942 JSON_ASSERT(use_count);
15943 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15944 const bool same_prefix = std::all_of(j.begin(), j.end(),
15945 [this, first_prefix, use_bjdata](const BasicJsonType& v)
15946 {
15947 return ubjson_prefix(v, use_bjdata) == first_prefix;
15948 });
15949
15950 std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
15951
15952 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15953 {
15954 prefix_required = false;
15955 oa->write_character(to_char_type('$'));
15956 oa->write_character(first_prefix);
15957 }
15958 }
15959
15960 if (use_count)
15961 {
15962 oa->write_character(to_char_type('#'));
15963 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15964 }
15965
15966 for (const auto& el : *j.m_data.m_value.object)
15967 {
15968 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15969 oa->write_characters(
15970 reinterpret_cast<const CharType*>(el.first.c_str()),
15971 el.first.size());
15972 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15973 }
15974
15975 if (!use_count)
15976 {
15977 oa->write_character(to_char_type('}'));
15978 }
15979
15980 break;
15981 }
15982
15983 case value_t::discarded:
15984 default:
15985 break;
15986 }
15987 }
15988
15989 private:
15991 // BSON //
15993
15998 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
15999 {
16000 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16001 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16002 {
16003 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16004 static_cast<void>(j);
16005 }
16006
16007 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16008 }
16009
16013 void write_bson_entry_header(const string_t& name,
16014 const std::uint8_t element_type)
16015 {
16016 oa->write_character(to_char_type(element_type)); // boolean
16017 oa->write_characters(
16018 reinterpret_cast<const CharType*>(name.c_str()),
16019 name.size() + 1u);
16020 }
16021
16025 void write_bson_boolean(const string_t& name,
16026 const bool value)
16027 {
16028 write_bson_entry_header(name, 0x08);
16029 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16030 }
16031
16035 void write_bson_double(const string_t& name,
16036 const double value)
16037 {
16038 write_bson_entry_header(name, 0x01);
16039 write_number<double>(value, true);
16040 }
16041
16045 static std::size_t calc_bson_string_size(const string_t& value)
16046 {
16047 return sizeof(std::int32_t) + value.size() + 1ul;
16048 }
16049
16053 void write_bson_string(const string_t& name,
16054 const string_t& value)
16055 {
16056 write_bson_entry_header(name, 0x02);
16057
16058 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16059 oa->write_characters(
16060 reinterpret_cast<const CharType*>(value.c_str()),
16061 value.size() + 1);
16062 }
16063
16067 void write_bson_null(const string_t& name)
16068 {
16069 write_bson_entry_header(name, 0x0A);
16070 }
16071
16075 static std::size_t calc_bson_integer_size(const std::int64_t value)
16076 {
16077 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16078 ? sizeof(std::int32_t)
16079 : sizeof(std::int64_t);
16080 }
16081
16085 void write_bson_integer(const string_t& name,
16086 const std::int64_t value)
16087 {
16088 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16089 {
16090 write_bson_entry_header(name, 0x10); // int32
16091 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16092 }
16093 else
16094 {
16095 write_bson_entry_header(name, 0x12); // int64
16096 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16097 }
16098 }
16099
16103 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16104 {
16105 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16106 ? sizeof(std::int32_t)
16107 : sizeof(std::int64_t);
16108 }
16109
16113 void write_bson_unsigned(const string_t& name,
16114 const BasicJsonType& j)
16115 {
16116 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16117 {
16118 write_bson_entry_header(name, 0x10 /* int32 */);
16119 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16120 }
16121 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16122 {
16123 write_bson_entry_header(name, 0x12 /* int64 */);
16124 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16125 }
16126 else
16127 {
16128 JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
16129 }
16130 }
16131
16135 void write_bson_object_entry(const string_t& name,
16136 const typename BasicJsonType::object_t& value)
16137 {
16138 write_bson_entry_header(name, 0x03); // object
16139 write_bson_object(value);
16140 }
16141
16145 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16146 {
16147 std::size_t array_index = 0ul;
16148
16149 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type& el)
16150 {
16151 return result + calc_bson_element_size(std::to_string(array_index++), el);
16152 });
16153
16154 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16155 }
16156
16160 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16161 {
16162 return sizeof(std::int32_t) + value.size() + 1ul;
16163 }
16164
16168 void write_bson_array(const string_t& name,
16169 const typename BasicJsonType::array_t& value)
16170 {
16171 write_bson_entry_header(name, 0x04); // array
16172 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16173
16174 std::size_t array_index = 0ul;
16175
16176 for (const auto& el : value)
16177 {
16178 write_bson_element(std::to_string(array_index++), el);
16179 }
16180
16181 oa->write_character(to_char_type(0x00));
16182 }
16183
16187 void write_bson_binary(const string_t& name,
16188 const binary_t& value)
16189 {
16190 write_bson_entry_header(name, 0x05);
16191
16192 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16193 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16194
16195 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16196 }
16197
16202 static std::size_t calc_bson_element_size(const string_t& name,
16203 const BasicJsonType& j)
16204 {
16205 const auto header_size = calc_bson_entry_header_size(name, j);
16206 switch (j.type())
16207 {
16208 case value_t::object:
16209 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16210
16211 case value_t::array:
16212 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16213
16214 case value_t::binary:
16215 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16216
16217 case value_t::boolean:
16218 return header_size + 1ul;
16219
16220 case value_t::number_float:
16221 return header_size + 8ul;
16222
16223 case value_t::number_integer:
16224 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16225
16226 case value_t::number_unsigned:
16227 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16228
16229 case value_t::string:
16230 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16231
16232 case value_t::null:
16233 return header_size + 0ul;
16234
16235 // LCOV_EXCL_START
16236 case value_t::discarded:
16237 default:
16238 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16239 return 0ul;
16240 // LCOV_EXCL_STOP
16241 }
16242 }
16243
16250 void write_bson_element(const string_t& name,
16251 const BasicJsonType& j)
16252 {
16253 switch (j.type())
16254 {
16255 case value_t::object:
16256 return write_bson_object_entry(name, *j.m_data.m_value.object);
16257
16258 case value_t::array:
16259 return write_bson_array(name, *j.m_data.m_value.array);
16260
16261 case value_t::binary:
16262 return write_bson_binary(name, *j.m_data.m_value.binary);
16263
16264 case value_t::boolean:
16265 return write_bson_boolean(name, j.m_data.m_value.boolean);
16266
16267 case value_t::number_float:
16268 return write_bson_double(name, j.m_data.m_value.number_float);
16269
16270 case value_t::number_integer:
16271 return write_bson_integer(name, j.m_data.m_value.number_integer);
16272
16273 case value_t::number_unsigned:
16274 return write_bson_unsigned(name, j);
16275
16276 case value_t::string:
16277 return write_bson_string(name, *j.m_data.m_value.string);
16278
16279 case value_t::null:
16280 return write_bson_null(name);
16281
16282 // LCOV_EXCL_START
16283 case value_t::discarded:
16284 default:
16285 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16286 return;
16287 // LCOV_EXCL_STOP
16288 }
16289 }
16290
16297 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16298 {
16299 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16300 [](size_t result, const typename BasicJsonType::object_t::value_type& el)
16301 {
16302 return result += calc_bson_element_size(el.first, el.second);
16303 });
16304
16305 return sizeof(std::int32_t) + document_size + 1ul;
16306 }
16307
16312 void write_bson_object(const typename BasicJsonType::object_t& value)
16313 {
16314 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16315
16316 for (const auto& el : value)
16317 {
16318 write_bson_element(el.first, el.second);
16319 }
16320
16321 oa->write_character(to_char_type(0x00));
16322 }
16323
16325 // CBOR //
16327
16328 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16329 {
16330 return to_char_type(0xFA); // Single-Precision Float
16331 }
16332
16333 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16334 {
16335 return to_char_type(0xFB); // Double-Precision Float
16336 }
16337
16339 // MsgPack //
16341
16342 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16343 {
16344 return to_char_type(0xCA); // float 32
16345 }
16346
16347 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16348 {
16349 return to_char_type(0xCB); // float 64
16350 }
16351
16353 // UBJSON //
16355
16356 // UBJSON: write number (floating point)
16357 template<typename NumberType, typename std::enable_if<
16358 std::is_floating_point<NumberType>::value, int>::type = 0>
16359 void write_number_with_ubjson_prefix(const NumberType n,
16360 const bool add_prefix,
16361 const bool use_bjdata)
16362 {
16363 if (add_prefix)
16364 {
16365 oa->write_character(get_ubjson_float_prefix(n));
16366 }
16367 write_number(n, use_bjdata);
16368 }
16369
16370 // UBJSON: write number (unsigned integer)
16371 template<typename NumberType, typename std::enable_if<
16372 std::is_unsigned<NumberType>::value, int>::type = 0>
16373 void write_number_with_ubjson_prefix(const NumberType n,
16374 const bool add_prefix,
16375 const bool use_bjdata)
16376 {
16377 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16378 {
16379 if (add_prefix)
16380 {
16381 oa->write_character(to_char_type('i')); // int8
16382 }
16383 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16384 }
16385 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16386 {
16387 if (add_prefix)
16388 {
16389 oa->write_character(to_char_type('U')); // uint8
16390 }
16391 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16392 }
16393 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16394 {
16395 if (add_prefix)
16396 {
16397 oa->write_character(to_char_type('I')); // int16
16398 }
16399 write_number(static_cast<std::int16_t>(n), use_bjdata);
16400 }
16401 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16402 {
16403 if (add_prefix)
16404 {
16405 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16406 }
16407 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16408 }
16409 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16410 {
16411 if (add_prefix)
16412 {
16413 oa->write_character(to_char_type('l')); // int32
16414 }
16415 write_number(static_cast<std::int32_t>(n), use_bjdata);
16416 }
16417 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16418 {
16419 if (add_prefix)
16420 {
16421 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16422 }
16423 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16424 }
16425 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16426 {
16427 if (add_prefix)
16428 {
16429 oa->write_character(to_char_type('L')); // int64
16430 }
16431 write_number(static_cast<std::int64_t>(n), use_bjdata);
16432 }
16433 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16434 {
16435 if (add_prefix)
16436 {
16437 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16438 }
16439 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16440 }
16441 else
16442 {
16443 if (add_prefix)
16444 {
16445 oa->write_character(to_char_type('H')); // high-precision number
16446 }
16447
16448 const auto number = BasicJsonType(n).dump();
16449 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16450 for (std::size_t i = 0; i < number.size(); ++i)
16451 {
16452 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16453 }
16454 }
16455 }
16456
16457 // UBJSON: write number (signed integer)
16458 template < typename NumberType, typename std::enable_if <
16459 std::is_signed<NumberType>::value &&
16460 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16461 void write_number_with_ubjson_prefix(const NumberType n,
16462 const bool add_prefix,
16463 const bool use_bjdata)
16464 {
16465 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16466 {
16467 if (add_prefix)
16468 {
16469 oa->write_character(to_char_type('i')); // int8
16470 }
16471 write_number(static_cast<std::int8_t>(n), use_bjdata);
16472 }
16473 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
16474 {
16475 if (add_prefix)
16476 {
16477 oa->write_character(to_char_type('U')); // uint8
16478 }
16479 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16480 }
16481 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16482 {
16483 if (add_prefix)
16484 {
16485 oa->write_character(to_char_type('I')); // int16
16486 }
16487 write_number(static_cast<std::int16_t>(n), use_bjdata);
16488 }
16489 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
16490 {
16491 if (add_prefix)
16492 {
16493 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16494 }
16495 write_number(static_cast<uint16_t>(n), use_bjdata);
16496 }
16497 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16498 {
16499 if (add_prefix)
16500 {
16501 oa->write_character(to_char_type('l')); // int32
16502 }
16503 write_number(static_cast<std::int32_t>(n), use_bjdata);
16504 }
16505 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
16506 {
16507 if (add_prefix)
16508 {
16509 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16510 }
16511 write_number(static_cast<uint32_t>(n), use_bjdata);
16512 }
16513 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16514 {
16515 if (add_prefix)
16516 {
16517 oa->write_character(to_char_type('L')); // int64
16518 }
16519 write_number(static_cast<std::int64_t>(n), use_bjdata);
16520 }
16521 // LCOV_EXCL_START
16522 else
16523 {
16524 if (add_prefix)
16525 {
16526 oa->write_character(to_char_type('H')); // high-precision number
16527 }
16528
16529 const auto number = BasicJsonType(n).dump();
16530 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16531 for (std::size_t i = 0; i < number.size(); ++i)
16532 {
16533 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16534 }
16535 }
16536 // LCOV_EXCL_STOP
16537 }
16538
16542 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16543 {
16544 switch (j.type())
16545 {
16546 case value_t::null:
16547 return 'Z';
16548
16549 case value_t::boolean:
16550 return j.m_data.m_value.boolean ? 'T' : 'F';
16551
16552 case value_t::number_integer:
16553 {
16554 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16555 {
16556 return 'i';
16557 }
16558 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16559 {
16560 return 'U';
16561 }
16562 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16563 {
16564 return 'I';
16565 }
16566 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16567 {
16568 return 'u';
16569 }
16570 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16571 {
16572 return 'l';
16573 }
16574 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16575 {
16576 return 'm';
16577 }
16578 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16579 {
16580 return 'L';
16581 }
16582 // anything else is treated as high-precision number
16583 return 'H'; // LCOV_EXCL_LINE
16584 }
16585
16586 case value_t::number_unsigned:
16587 {
16588 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16589 {
16590 return 'i';
16591 }
16592 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16593 {
16594 return 'U';
16595 }
16596 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16597 {
16598 return 'I';
16599 }
16600 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16601 {
16602 return 'u';
16603 }
16604 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16605 {
16606 return 'l';
16607 }
16608 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16609 {
16610 return 'm';
16611 }
16612 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16613 {
16614 return 'L';
16615 }
16616 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16617 {
16618 return 'M';
16619 }
16620 // anything else is treated as high-precision number
16621 return 'H'; // LCOV_EXCL_LINE
16622 }
16623
16624 case value_t::number_float:
16625 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16626
16627 case value_t::string:
16628 return 'S';
16629
16630 case value_t::array: // fallthrough
16631 case value_t::binary:
16632 return '[';
16633
16634 case value_t::object:
16635 return '{';
16636
16637 case value_t::discarded:
16638 default: // discarded values
16639 return 'N';
16640 }
16641 }
16642
16643 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16644 {
16645 return 'd'; // float 32
16646 }
16647
16648 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16649 {
16650 return 'D'; // float 64
16651 }
16652
16656 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16657 {
16658 std::map<string_t, CharType> bjdtype = { {"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16659 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16660 };
16661
16662 string_t key = "_ArrayType_";
16663 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16664 if (it == bjdtype.end())
16665 {
16666 return true;
16667 }
16668 CharType dtype = it->second;
16669
16670 key = "_ArraySize_";
16671 std::size_t len = (value.at(key).empty() ? 0 : 1);
16672 for (const auto& el : value.at(key))
16673 {
16674 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16675 }
16676
16677 key = "_ArrayData_";
16678 if (value.at(key).size() != len)
16679 {
16680 return true;
16681 }
16682
16683 oa->write_character('[');
16684 oa->write_character('$');
16685 oa->write_character(dtype);
16686 oa->write_character('#');
16687
16688 key = "_ArraySize_";
16689 write_ubjson(value.at(key), use_count, use_type, true, true);
16690
16691 key = "_ArrayData_";
16692 if (dtype == 'U' || dtype == 'C')
16693 {
16694 for (const auto& el : value.at(key))
16695 {
16696 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16697 }
16698 }
16699 else if (dtype == 'i')
16700 {
16701 for (const auto& el : value.at(key))
16702 {
16703 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16704 }
16705 }
16706 else if (dtype == 'u')
16707 {
16708 for (const auto& el : value.at(key))
16709 {
16710 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16711 }
16712 }
16713 else if (dtype == 'I')
16714 {
16715 for (const auto& el : value.at(key))
16716 {
16717 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16718 }
16719 }
16720 else if (dtype == 'm')
16721 {
16722 for (const auto& el : value.at(key))
16723 {
16724 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16725 }
16726 }
16727 else if (dtype == 'l')
16728 {
16729 for (const auto& el : value.at(key))
16730 {
16731 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16732 }
16733 }
16734 else if (dtype == 'M')
16735 {
16736 for (const auto& el : value.at(key))
16737 {
16738 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16739 }
16740 }
16741 else if (dtype == 'L')
16742 {
16743 for (const auto& el : value.at(key))
16744 {
16745 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16746 }
16747 }
16748 else if (dtype == 'd')
16749 {
16750 for (const auto& el : value.at(key))
16751 {
16752 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16753 }
16754 }
16755 else if (dtype == 'D')
16756 {
16757 for (const auto& el : value.at(key))
16758 {
16759 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16760 }
16761 }
16762 return false;
16763 }
16764
16766 // Utility functions //
16768
16769 /*
16770 @brief write a number to output input
16771 @param[in] n number of type @a NumberType
16772 @param[in] OutputIsLittleEndian Set to true if output data is
16773 required to be little endian
16774 @tparam NumberType the type of the number
16775
16776 @note This function needs to respect the system's endianness, because bytes
16777 in CBOR, MessagePack, and UBJSON are stored in network order (big
16778 endian) and therefore need reordering on little endian systems.
16779 On the other hand, BSON and BJData use little endian and should reorder
16780 on big endian systems.
16781 */
16782 template<typename NumberType>
16783 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16784 {
16785 // step 1: write number to array of length NumberType
16786 std::array<CharType, sizeof(NumberType)> vec{};
16787 std::memcpy(vec.data(), &n, sizeof(NumberType));
16788
16789 // step 2: write array to output (with possible reordering)
16790 if (is_little_endian != OutputIsLittleEndian)
16791 {
16792 // reverse byte order prior to conversion if necessary
16793 std::reverse(vec.begin(), vec.end());
16794 }
16795
16796 oa->write_characters(vec.data(), sizeof(NumberType));
16797 }
16798
16799 void write_compact_float(const number_float_t n, detail::input_format_t format)
16800 {
16801#ifdef __GNUC__
16802#pragma GCC diagnostic push
16803#pragma GCC diagnostic ignored "-Wfloat-equal"
16804#endif
16805 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16806 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16807 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16808 {
16809 oa->write_character(format == detail::input_format_t::cbor
16810 ? get_cbor_float_prefix(static_cast<float>(n))
16811 : get_msgpack_float_prefix(static_cast<float>(n)));
16812 write_number(static_cast<float>(n));
16813 }
16814 else
16815 {
16816 oa->write_character(format == detail::input_format_t::cbor
16817 ? get_cbor_float_prefix(n)
16818 : get_msgpack_float_prefix(n));
16819 write_number(n);
16820 }
16821#ifdef __GNUC__
16822#pragma GCC diagnostic pop
16823#endif
16824 }
16825
16826 public:
16827 // The following to_char_type functions are implement the conversion
16828 // between uint8_t and CharType. In case CharType is not unsigned,
16829 // such a conversion is required to allow values greater than 128.
16830 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16831 template < typename C = CharType,
16832 enable_if_t < std::is_signed<C>::value&& std::is_signed<char>::value >* = nullptr >
16833 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16834 {
16835 return *reinterpret_cast<char*>(&x);
16836 }
16837
16838 template < typename C = CharType,
16839 enable_if_t < std::is_signed<C>::value&& std::is_unsigned<char>::value >* = nullptr >
16840 static CharType to_char_type(std::uint8_t x) noexcept
16841 {
16842 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16843 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16844 CharType result;
16845 std::memcpy(&result, &x, sizeof(x));
16846 return result;
16847 }
16848
16849 template<typename C = CharType,
16851 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16852 {
16853 return x;
16854 }
16855
16856 template < typename InputCharType, typename C = CharType,
16857 enable_if_t <
16858 std::is_signed<C>::value&&
16859 std::is_signed<char>::value&&
16860 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16861 >* = nullptr >
16862 static constexpr CharType to_char_type(InputCharType x) noexcept
16863 {
16864 return x;
16865 }
16866
16867 private:
16869 const bool is_little_endian = little_endianness();
16870
16872 output_adapter_t<CharType> oa = nullptr;
16873 };
16874
16875} // namespace detail
16877
16878// #include <nlohmann/detail/output/output_adapters.hpp>
16879
16880// #include <nlohmann/detail/output/serializer.hpp>
16881// __ _____ _____ _____
16882// __| | __| | | | JSON for Modern C++
16883// | | |__ | | | | | | version 3.11.3
16884// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16885//
16886// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
16887// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16888// SPDX-License-Identifier: MIT
16889
16890
16891
16892#include <algorithm> // reverse, remove, fill, find, none_of
16893#include <array> // array
16894#include <clocale> // localeconv, lconv
16895#include <cmath> // labs, isfinite, isnan, signbit
16896#include <cstddef> // size_t, ptrdiff_t
16897#include <cstdint> // uint8_t
16898#include <cstdio> // snprintf
16899#include <limits> // numeric_limits
16900#include <string> // string, char_traits
16901#include <iomanip> // setfill, setw
16902#include <type_traits> // is_same
16903#include <utility> // move
16904
16905// #include <nlohmann/detail/conversions/to_chars.hpp>
16906// __ _____ _____ _____
16907// __| | __| | | | JSON for Modern C++
16908// | | |__ | | | | | | version 3.11.3
16909// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16910//
16911// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16912// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16913// SPDX-License-Identifier: MIT
16914
16915
16916
16917#include <array> // array
16918#include <cmath> // signbit, isfinite
16919#include <cstdint> // intN_t, uintN_t
16920#include <cstring> // memcpy, memmove
16921#include <limits> // numeric_limits
16922#include <type_traits> // conditional
16923
16924// #include <nlohmann/detail/macro_scope.hpp>
16925
16926
16928namespace detail
16929{
16930
16950 namespace dtoa_impl
16951 {
16952
16953 template<typename Target, typename Source>
16954 Target reinterpret_bits(const Source source)
16955 {
16956 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16957
16958 Target target;
16959 std::memcpy(&target, &source, sizeof(Source));
16960 return target;
16961 }
16962
16963 struct diyfp // f * 2^e
16964 {
16965 static constexpr int kPrecision = 64; // = q
16966
16967 std::uint64_t f = 0;
16968 int e = 0;
16969
16970 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16971
16976 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16977 {
16978 JSON_ASSERT(x.e == y.e);
16979 JSON_ASSERT(x.f >= y.f);
16980
16981 return { x.f - y.f, x.e };
16982 }
16983
16988 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
16989 {
16990 static_assert(kPrecision == 64, "internal error");
16991
16992 // Computes:
16993 // f = round((x.f * y.f) / 2^q)
16994 // e = x.e + y.e + q
16995
16996 // Emulate the 64-bit * 64-bit multiplication:
16997 //
16998 // p = u * v
16999 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17000 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17001 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17002 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17003 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17004 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17005 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17006 //
17007 // (Since Q might be larger than 2^32 - 1)
17008 //
17009 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17010 //
17011 // (Q_hi + H does not overflow a 64-bit int)
17012 //
17013 // = p_lo + 2^64 p_hi
17014
17015 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17016 const std::uint64_t u_hi = x.f >> 32u;
17017 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17018 const std::uint64_t v_hi = y.f >> 32u;
17019
17020 const std::uint64_t p0 = u_lo * v_lo;
17021 const std::uint64_t p1 = u_lo * v_hi;
17022 const std::uint64_t p2 = u_hi * v_lo;
17023 const std::uint64_t p3 = u_hi * v_hi;
17024
17025 const std::uint64_t p0_hi = p0 >> 32u;
17026 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17027 const std::uint64_t p1_hi = p1 >> 32u;
17028 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17029 const std::uint64_t p2_hi = p2 >> 32u;
17030
17031 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17032
17033 // The full product might now be computed as
17034 //
17035 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17036 // p_lo = p0_lo + (Q << 32)
17037 //
17038 // But in this particular case here, the full p_lo is not required.
17039 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17040 // Q_hi + 1 does not overflow).
17041
17042 Q += std::uint64_t{ 1 } << (64u - 32u - 1u); // round, ties up
17043
17044 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17045
17046 return { h, x.e + y.e + 64 };
17047 }
17048
17053 static diyfp normalize(diyfp x) noexcept
17054 {
17055 JSON_ASSERT(x.f != 0);
17056
17057 while ((x.f >> 63u) == 0)
17058 {
17059 x.f <<= 1u;
17060 x.e--;
17061 }
17062
17063 return x;
17064 }
17065
17070 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17071 {
17072 const int delta = x.e - target_exponent;
17073
17074 JSON_ASSERT(delta >= 0);
17075 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17076
17077 return { x.f << delta, target_exponent };
17078 }
17079 };
17080
17082 {
17086 };
17087
17094 template<typename FloatType>
17096 {
17097 JSON_ASSERT(std::isfinite(value));
17098 JSON_ASSERT(value > 0);
17099
17100 // Convert the IEEE representation into a diyfp.
17101 //
17102 // If v is denormal:
17103 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17104 // If v is normalized:
17105 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17106
17107 static_assert(std::numeric_limits<FloatType>::is_iec559,
17108 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17109
17110 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17111 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17112 constexpr int kMinExp = 1 - kBias;
17113 constexpr std::uint64_t kHiddenBit = std::uint64_t{ 1 } << (kPrecision - 1); // = 2^(p-1)
17114
17115 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17116
17117 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17118 const std::uint64_t E = bits >> (kPrecision - 1);
17119 const std::uint64_t F = bits & (kHiddenBit - 1);
17120
17121 const bool is_denormal = E == 0;
17122 const diyfp v = is_denormal
17123 ? diyfp(F, kMinExp)
17124 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17125
17126 // Compute the boundaries m- and m+ of the floating-point value
17127 // v = f * 2^e.
17128 //
17129 // Determine v- and v+, the floating-point predecessor and successor if v,
17130 // respectively.
17131 //
17132 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17133 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17134 //
17135 // v+ = v + 2^e
17136 //
17137 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17138 // between m- and m+ round to v, regardless of how the input rounding
17139 // algorithm breaks ties.
17140 //
17141 // ---+-------------+-------------+-------------+-------------+--- (A)
17142 // v- m- v m+ v+
17143 //
17144 // -----------------+------+------+-------------+-------------+--- (B)
17145 // v- m- v m+ v+
17146
17147 const bool lower_boundary_is_closer = F == 0 && E > 1;
17148 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17149 const diyfp m_minus = lower_boundary_is_closer
17150 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17151 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17152
17153 // Determine the normalized w+ = m+.
17154 const diyfp w_plus = diyfp::normalize(m_plus);
17155
17156 // Determine w- = m- such that e_(w-) = e_(w+).
17157 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17158
17159 return { diyfp::normalize(v), w_minus, w_plus };
17160 }
17161
17162 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
17163 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17164 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
17165 //
17166 // alpha <= e = e_c + e_w + q <= gamma
17167 //
17168 // or
17169 //
17170 // f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17171 // <= f_c * f_w * 2^gamma
17172 //
17173 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17174 //
17175 // 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17176 //
17177 // or
17178 //
17179 // 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17180 //
17181 // The choice of (alpha,gamma) determines the size of the table and the form of
17182 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17183 // in practice:
17184 //
17185 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
17186 // processed independently: An integral part p1, and a fractional part p2:
17187 //
17188 // f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17189 // = (f div 2^-e) + (f mod 2^-e) * 2^e
17190 // = p1 + p2 * 2^e
17191 //
17192 // The conversion of p1 into decimal form requires a series of divisions and
17193 // modulos by (a power of) 10. These operations are faster for 32-bit than for
17194 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17195 // achieved by choosing
17196 //
17197 // -e >= 32 or e <= -32 := gamma
17198 //
17199 // In order to convert the fractional part
17200 //
17201 // p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17202 //
17203 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17204 // d[-i] are extracted in order:
17205 //
17206 // (10 * p2) div 2^-e = d[-1]
17207 // (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17208 //
17209 // The multiplication by 10 must not overflow. It is sufficient to choose
17210 //
17211 // 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17212 //
17213 // Since p2 = f mod 2^-e < 2^-e,
17214 //
17215 // -e <= 60 or e >= -60 := alpha
17216
17217 constexpr int kAlpha = -60;
17218 constexpr int kGamma = -32;
17219
17220 struct cached_power // c = f * 2^e ~= 10^k
17221 {
17222 std::uint64_t f;
17223 int e;
17224 int k;
17225 };
17226
17235 {
17236 // Now
17237 //
17238 // alpha <= e_c + e + q <= gamma (1)
17239 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17240 //
17241 // and since the c's are normalized, 2^(q-1) <= f_c,
17242 //
17243 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17244 // ==> 2^(alpha - e - 1) <= c
17245 //
17246 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17247 //
17248 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17249 // = ceil( (alpha - e - 1) * log_10(2) )
17250 //
17251 // From the paper:
17252 // "In theory the result of the procedure could be wrong since c is rounded,
17253 // and the computation itself is approximated [...]. In practice, however,
17254 // this simple function is sufficient."
17255 //
17256 // For IEEE double precision floating-point numbers converted into
17257 // normalized diyfp's w = f * 2^e, with q = 64,
17258 //
17259 // e >= -1022 (min IEEE exponent)
17260 // -52 (p - 1)
17261 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17262 // -11 (normalize the diyfp)
17263 // = -1137
17264 //
17265 // and
17266 //
17267 // e <= +1023 (max IEEE exponent)
17268 // -52 (p - 1)
17269 // -11 (normalize the diyfp)
17270 // = 960
17271 //
17272 // This binary exponent range [-1137,960] results in a decimal exponent
17273 // range [-307,324]. One does not need to store a cached power for each
17274 // k in this range. For each such k it suffices to find a cached power
17275 // such that the exponent of the product lies in [alpha,gamma].
17276 // This implies that the difference of the decimal exponents of adjacent
17277 // table entries must be less than or equal to
17278 //
17279 // floor( (gamma - alpha) * log_10(2) ) = 8.
17280 //
17281 // (A smaller distance gamma-alpha would require a larger table.)
17282
17283 // NB:
17284 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17285
17286 constexpr int kCachedPowersMinDecExp = -300;
17287 constexpr int kCachedPowersDecStep = 8;
17288
17289 static constexpr std::array<cached_power, 79> kCachedPowers =
17290 {
17291 {
17292 { 0xAB70FE17C79AC6CA, -1060, -300 },
17293 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17294 { 0xBE5691EF416BD60C, -1007, -284 },
17295 { 0x8DD01FAD907FFC3C, -980, -276 },
17296 { 0xD3515C2831559A83, -954, -268 },
17297 { 0x9D71AC8FADA6C9B5, -927, -260 },
17298 { 0xEA9C227723EE8BCB, -901, -252 },
17299 { 0xAECC49914078536D, -874, -244 },
17300 { 0x823C12795DB6CE57, -847, -236 },
17301 { 0xC21094364DFB5637, -821, -228 },
17302 { 0x9096EA6F3848984F, -794, -220 },
17303 { 0xD77485CB25823AC7, -768, -212 },
17304 { 0xA086CFCD97BF97F4, -741, -204 },
17305 { 0xEF340A98172AACE5, -715, -196 },
17306 { 0xB23867FB2A35B28E, -688, -188 },
17307 { 0x84C8D4DFD2C63F3B, -661, -180 },
17308 { 0xC5DD44271AD3CDBA, -635, -172 },
17309 { 0x936B9FCEBB25C996, -608, -164 },
17310 { 0xDBAC6C247D62A584, -582, -156 },
17311 { 0xA3AB66580D5FDAF6, -555, -148 },
17312 { 0xF3E2F893DEC3F126, -529, -140 },
17313 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17314 { 0x87625F056C7C4A8B, -475, -124 },
17315 { 0xC9BCFF6034C13053, -449, -116 },
17316 { 0x964E858C91BA2655, -422, -108 },
17317 { 0xDFF9772470297EBD, -396, -100 },
17318 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17319 { 0xF8A95FCF88747D94, -343, -84 },
17320 { 0xB94470938FA89BCF, -316, -76 },
17321 { 0x8A08F0F8BF0F156B, -289, -68 },
17322 { 0xCDB02555653131B6, -263, -60 },
17323 { 0x993FE2C6D07B7FAC, -236, -52 },
17324 { 0xE45C10C42A2B3B06, -210, -44 },
17325 { 0xAA242499697392D3, -183, -36 },
17326 { 0xFD87B5F28300CA0E, -157, -28 },
17327 { 0xBCE5086492111AEB, -130, -20 },
17328 { 0x8CBCCC096F5088CC, -103, -12 },
17329 { 0xD1B71758E219652C, -77, -4 },
17330 { 0x9C40000000000000, -50, 4 },
17331 { 0xE8D4A51000000000, -24, 12 },
17332 { 0xAD78EBC5AC620000, 3, 20 },
17333 { 0x813F3978F8940984, 30, 28 },
17334 { 0xC097CE7BC90715B3, 56, 36 },
17335 { 0x8F7E32CE7BEA5C70, 83, 44 },
17336 { 0xD5D238A4ABE98068, 109, 52 },
17337 { 0x9F4F2726179A2245, 136, 60 },
17338 { 0xED63A231D4C4FB27, 162, 68 },
17339 { 0xB0DE65388CC8ADA8, 189, 76 },
17340 { 0x83C7088E1AAB65DB, 216, 84 },
17341 { 0xC45D1DF942711D9A, 242, 92 },
17342 { 0x924D692CA61BE758, 269, 100 },
17343 { 0xDA01EE641A708DEA, 295, 108 },
17344 { 0xA26DA3999AEF774A, 322, 116 },
17345 { 0xF209787BB47D6B85, 348, 124 },
17346 { 0xB454E4A179DD1877, 375, 132 },
17347 { 0x865B86925B9BC5C2, 402, 140 },
17348 { 0xC83553C5C8965D3D, 428, 148 },
17349 { 0x952AB45CFA97A0B3, 455, 156 },
17350 { 0xDE469FBD99A05FE3, 481, 164 },
17351 { 0xA59BC234DB398C25, 508, 172 },
17352 { 0xF6C69A72A3989F5C, 534, 180 },
17353 { 0xB7DCBF5354E9BECE, 561, 188 },
17354 { 0x88FCF317F22241E2, 588, 196 },
17355 { 0xCC20CE9BD35C78A5, 614, 204 },
17356 { 0x98165AF37B2153DF, 641, 212 },
17357 { 0xE2A0B5DC971F303A, 667, 220 },
17358 { 0xA8D9D1535CE3B396, 694, 228 },
17359 { 0xFB9B7CD9A4A7443C, 720, 236 },
17360 { 0xBB764C4CA7A44410, 747, 244 },
17361 { 0x8BAB8EEFB6409C1A, 774, 252 },
17362 { 0xD01FEF10A657842C, 800, 260 },
17363 { 0x9B10A4E5E9913129, 827, 268 },
17364 { 0xE7109BFBA19C0C9D, 853, 276 },
17365 { 0xAC2820D9623BF429, 880, 284 },
17366 { 0x80444B5E7AA7CF85, 907, 292 },
17367 { 0xBF21E44003ACDD2D, 933, 300 },
17368 { 0x8E679C2F5E44FF8F, 960, 308 },
17369 { 0xD433179D9C8CB841, 986, 316 },
17370 { 0x9E19DB92B4E31BA9, 1013, 324 },
17371 }
17372 };
17373
17374 // This computation gives exactly the same results for k as
17375 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17376 // for |e| <= 1500, but doesn't require floating-point operations.
17377 // NB: log_10(2) ~= 78913 / 2^18
17378 JSON_ASSERT(e >= -1500);
17379 JSON_ASSERT(e <= 1500);
17380 const int f = kAlpha - e - 1;
17381 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17382
17383 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17384 JSON_ASSERT(index >= 0);
17385 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17386
17387 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17388 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17389 JSON_ASSERT(kGamma >= cached.e + e + 64);
17390
17391 return cached;
17392 }
17393
17398 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17399 {
17400 // LCOV_EXCL_START
17401 if (n >= 1000000000)
17402 {
17403 pow10 = 1000000000;
17404 return 10;
17405 }
17406 // LCOV_EXCL_STOP
17407 if (n >= 100000000)
17408 {
17409 pow10 = 100000000;
17410 return 9;
17411 }
17412 if (n >= 10000000)
17413 {
17414 pow10 = 10000000;
17415 return 8;
17416 }
17417 if (n >= 1000000)
17418 {
17419 pow10 = 1000000;
17420 return 7;
17421 }
17422 if (n >= 100000)
17423 {
17424 pow10 = 100000;
17425 return 6;
17426 }
17427 if (n >= 10000)
17428 {
17429 pow10 = 10000;
17430 return 5;
17431 }
17432 if (n >= 1000)
17433 {
17434 pow10 = 1000;
17435 return 4;
17436 }
17437 if (n >= 100)
17438 {
17439 pow10 = 100;
17440 return 3;
17441 }
17442 if (n >= 10)
17443 {
17444 pow10 = 10;
17445 return 2;
17446 }
17447
17448 pow10 = 1;
17449 return 1;
17450 }
17451
17452 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17453 std::uint64_t rest, std::uint64_t ten_k)
17454 {
17455 JSON_ASSERT(len >= 1);
17456 JSON_ASSERT(dist <= delta);
17457 JSON_ASSERT(rest <= delta);
17458 JSON_ASSERT(ten_k > 0);
17459
17460 // <--------------------------- delta ---->
17461 // <---- dist --------->
17462 // --------------[------------------+-------------------]--------------
17463 // M- w M+
17464 //
17465 // ten_k
17466 // <------>
17467 // <---- rest ---->
17468 // --------------[------------------+----+--------------]--------------
17469 // w V
17470 // = buf * 10^k
17471 //
17472 // ten_k represents a unit-in-the-last-place in the decimal representation
17473 // stored in buf.
17474 // Decrement buf by ten_k while this takes buf closer to w.
17475
17476 // The tests are written in this order to avoid overflow in unsigned
17477 // integer arithmetic.
17478
17479 while (rest < dist
17480 && delta - rest >= ten_k
17481 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17482 {
17483 JSON_ASSERT(buf[len - 1] != '0');
17484 buf[len - 1]--;
17485 rest += ten_k;
17486 }
17487 }
17488
17493 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17494 diyfp M_minus, diyfp w, diyfp M_plus)
17495 {
17496 static_assert(kAlpha >= -60, "internal error");
17497 static_assert(kGamma <= -32, "internal error");
17498
17499 // Generates the digits (and the exponent) of a decimal floating-point
17500 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17501 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17502 //
17503 // <--------------------------- delta ---->
17504 // <---- dist --------->
17505 // --------------[------------------+-------------------]--------------
17506 // M- w M+
17507 //
17508 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17509 // V is in [M-,M+].
17510
17511 JSON_ASSERT(M_plus.e >= kAlpha);
17512 JSON_ASSERT(M_plus.e <= kGamma);
17513
17514 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17515 std::uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
17516
17517 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17518 //
17519 // M+ = f * 2^e
17520 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17521 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17522 // = p1 + p2 * 2^e
17523
17524 const diyfp one(std::uint64_t{ 1 } << -M_plus.e, M_plus.e);
17525
17526 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
17527 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17528
17529 // 1)
17530 //
17531 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17532
17533 JSON_ASSERT(p1 > 0);
17534
17535 std::uint32_t pow10{};
17536 const int k = find_largest_pow10(p1, pow10);
17537
17538 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17539 //
17540 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17541 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17542 //
17543 // M+ = p1 + p2 * 2^e
17544 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17545 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17546 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17547 //
17548 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17549 //
17550 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17551 //
17552 // but stop as soon as
17553 //
17554 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17555
17556 int n = k;
17557 while (n > 0)
17558 {
17559 // Invariants:
17560 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17561 // pow10 = 10^(n-1) <= p1 < 10^n
17562 //
17563 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17564 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17565 //
17566 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17567 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17568 //
17569 JSON_ASSERT(d <= 9);
17570 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17571 //
17572 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17573 //
17574 p1 = r;
17575 n--;
17576 //
17577 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17578 // pow10 = 10^n
17579 //
17580
17581 // Now check if enough digits have been generated.
17582 // Compute
17583 //
17584 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17585 //
17586 // Note:
17587 // Since rest and delta share the same exponent e, it suffices to
17588 // compare the significands.
17589 const std::uint64_t rest = (std::uint64_t{ p1 } << -one.e) + p2;
17590 if (rest <= delta)
17591 {
17592 // V = buffer * 10^n, with M- <= V <= M+.
17593
17594 decimal_exponent += n;
17595
17596 // We may now just stop. But instead look if the buffer could be
17597 // decremented to bring V closer to w.
17598 //
17599 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17600 // The rounding procedure works with diyfp's with an implicit
17601 // exponent of e.
17602 //
17603 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17604 //
17605 const std::uint64_t ten_n = std::uint64_t{ pow10 } << -one.e;
17606 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17607
17608 return;
17609 }
17610
17611 pow10 /= 10;
17612 //
17613 // pow10 = 10^(n-1) <= p1 < 10^n
17614 // Invariants restored.
17615 }
17616
17617 // 2)
17618 //
17619 // The digits of the integral part have been generated:
17620 //
17621 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17622 // = buffer + p2 * 2^e
17623 //
17624 // Now generate the digits of the fractional part p2 * 2^e.
17625 //
17626 // Note:
17627 // No decimal point is generated: the exponent is adjusted instead.
17628 //
17629 // p2 actually represents the fraction
17630 //
17631 // p2 * 2^e
17632 // = p2 / 2^-e
17633 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17634 //
17635 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17636 //
17637 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17638 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17639 //
17640 // using
17641 //
17642 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17643 // = ( d) * 2^-e + ( r)
17644 //
17645 // or
17646 // 10^m * p2 * 2^e = d + r * 2^e
17647 //
17648 // i.e.
17649 //
17650 // M+ = buffer + p2 * 2^e
17651 // = buffer + 10^-m * (d + r * 2^e)
17652 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17653 //
17654 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17655
17656 JSON_ASSERT(p2 > delta);
17657
17658 int m = 0;
17659 for (;;)
17660 {
17661 // Invariant:
17662 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17663 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17664 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17665 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17666 //
17667 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17668 p2 *= 10;
17669 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17670 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17671 //
17672 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17673 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17674 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17675 //
17676 JSON_ASSERT(d <= 9);
17677 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17678 //
17679 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17680 //
17681 p2 = r;
17682 m++;
17683 //
17684 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17685 // Invariant restored.
17686
17687 // Check if enough digits have been generated.
17688 //
17689 // 10^-m * p2 * 2^e <= delta * 2^e
17690 // p2 * 2^e <= 10^m * delta * 2^e
17691 // p2 <= 10^m * delta
17692 delta *= 10;
17693 dist *= 10;
17694 if (p2 <= delta)
17695 {
17696 break;
17697 }
17698 }
17699
17700 // V = buffer * 10^-m, with M- <= V <= M+.
17701
17702 decimal_exponent -= m;
17703
17704 // 1 ulp in the decimal representation is now 10^-m.
17705 // Since delta and dist are now scaled by 10^m, we need to do the
17706 // same with ulp in order to keep the units in sync.
17707 //
17708 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17709 //
17710 const std::uint64_t ten_m = one.f;
17711 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17712
17713 // By construction this algorithm generates the shortest possible decimal
17714 // number (Loitsch, Theorem 6.2) which rounds back to w.
17715 // For an input number of precision p, at least
17716 //
17717 // N = 1 + ceil(p * log_10(2))
17718 //
17719 // decimal digits are sufficient to identify all binary floating-point
17720 // numbers (Matula, "In-and-Out conversions").
17721 // This implies that the algorithm does not produce more than N decimal
17722 // digits.
17723 //
17724 // N = 17 for p = 53 (IEEE double precision)
17725 // N = 9 for p = 24 (IEEE single precision)
17726 }
17727
17734 inline void grisu2(char* buf, int& len, int& decimal_exponent,
17735 diyfp m_minus, diyfp v, diyfp m_plus)
17736 {
17737 JSON_ASSERT(m_plus.e == m_minus.e);
17738 JSON_ASSERT(m_plus.e == v.e);
17739
17740 // --------(-----------------------+-----------------------)-------- (A)
17741 // m- v m+
17742 //
17743 // --------------------(-----------+-----------------------)-------- (B)
17744 // m- v m+
17745 //
17746 // First scale v (and m- and m+) such that the exponent is in the range
17747 // [alpha, gamma].
17748
17749 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17750
17751 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17752
17753 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17754 const diyfp w = diyfp::mul(v, c_minus_k);
17755 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17756 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17757
17758 // ----(---+---)---------------(---+---)---------------(---+---)----
17759 // w- w w+
17760 // = c*m- = c*v = c*m+
17761 //
17762 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17763 // w+ are now off by a small amount.
17764 // In fact:
17765 //
17766 // w - v * 10^k < 1 ulp
17767 //
17768 // To account for this inaccuracy, add resp. subtract 1 ulp.
17769 //
17770 // --------+---[---------------(---+---)---------------]---+--------
17771 // w- M- w M+ w+
17772 //
17773 // Now any number in [M-, M+] (bounds included) will round to w when input,
17774 // regardless of how the input rounding algorithm breaks ties.
17775 //
17776 // And digit_gen generates the shortest possible such number in [M-, M+].
17777 // Note that this does not mean that Grisu2 always generates the shortest
17778 // possible number in the interval (m-, m+).
17779 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17780 const diyfp M_plus(w_plus.f - 1, w_plus.e);
17781
17782 decimal_exponent = -cached.k; // = -(-k) = k
17783
17784 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17785 }
17786
17792 template<typename FloatType>
17794 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17795 {
17796 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17797 "internal error: not enough precision");
17798
17799 JSON_ASSERT(std::isfinite(value));
17800 JSON_ASSERT(value > 0);
17801
17802 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17803 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17804 // decimal representations are not exactly "short".
17805 //
17806 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17807 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17808 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17809 // does.
17810 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17811 // representation using the corresponding std::from_chars function recovers value exactly". That
17812 // indicates that single precision floating-point numbers should be recovered using
17813 // 'std::strtof'.
17814 //
17815 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17816 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17817 // value is off by 1 ulp.
17818#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17819 const boundaries w = compute_boundaries(static_cast<double>(value));
17820#else
17822#endif
17823
17824 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17825 }
17826
17834 inline char* append_exponent(char* buf, int e)
17835 {
17836 JSON_ASSERT(e > -1000);
17837 JSON_ASSERT(e < 1000);
17838
17839 if (e < 0)
17840 {
17841 e = -e;
17842 *buf++ = '-';
17843 }
17844 else
17845 {
17846 *buf++ = '+';
17847 }
17848
17849 auto k = static_cast<std::uint32_t>(e);
17850 if (k < 10)
17851 {
17852 // Always print at least two digits in the exponent.
17853 // This is for compatibility with printf("%g").
17854 *buf++ = '0';
17855 *buf++ = static_cast<char>('0' + k);
17856 }
17857 else if (k < 100)
17858 {
17859 *buf++ = static_cast<char>('0' + k / 10);
17860 k %= 10;
17861 *buf++ = static_cast<char>('0' + k);
17862 }
17863 else
17864 {
17865 *buf++ = static_cast<char>('0' + k / 100);
17866 k %= 100;
17867 *buf++ = static_cast<char>('0' + k / 10);
17868 k %= 10;
17869 *buf++ = static_cast<char>('0' + k);
17870 }
17871
17872 return buf;
17873 }
17874
17886 inline char* format_buffer(char* buf, int len, int decimal_exponent,
17887 int min_exp, int max_exp)
17888 {
17889 JSON_ASSERT(min_exp < 0);
17890 JSON_ASSERT(max_exp > 0);
17891
17892 const int k = len;
17893 const int n = len + decimal_exponent;
17894
17895 // v = buf * 10^(n-k)
17896 // k is the length of the buffer (number of decimal digits)
17897 // n is the position of the decimal point relative to the start of the buffer.
17898
17899 if (k <= n && n <= max_exp)
17900 {
17901 // digits[000]
17902 // len <= max_exp + 2
17903
17904 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17905 // Make it look like a floating-point number (#362, #378)
17906 buf[n + 0] = '.';
17907 buf[n + 1] = '0';
17908 return buf + (static_cast<size_t>(n) + 2);
17909 }
17910
17911 if (0 < n && n <= max_exp)
17912 {
17913 // dig.its
17914 // len <= max_digits10 + 1
17915
17916 JSON_ASSERT(k > n);
17917
17918 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17919 buf[n] = '.';
17920 return buf + (static_cast<size_t>(k) + 1U);
17921 }
17922
17923 if (min_exp < n && n <= 0)
17924 {
17925 // 0.[000]digits
17926 // len <= 2 + (-min_exp - 1) + max_digits10
17927
17928 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17929 buf[0] = '0';
17930 buf[1] = '.';
17931 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17932 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17933 }
17934
17935 if (k == 1)
17936 {
17937 // dE+123
17938 // len <= 1 + 5
17939
17940 buf += 1;
17941 }
17942 else
17943 {
17944 // d.igitsE+123
17945 // len <= max_digits10 + 1 + 5
17946
17947 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17948 buf[1] = '.';
17949 buf += 1 + static_cast<size_t>(k);
17950 }
17951
17952 *buf++ = 'e';
17953 return append_exponent(buf, n - 1);
17954 }
17955
17956 } // namespace dtoa_impl
17957
17968 template<typename FloatType>
17971 char* to_chars(char* first, const char* last, FloatType value)
17972 {
17973 static_cast<void>(last); // maybe unused - fix warning
17974 JSON_ASSERT(std::isfinite(value));
17975
17976 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17977 if (std::signbit(value))
17978 {
17979 value = -value;
17980 *first++ = '-';
17981 }
17982
17983#ifdef __GNUC__
17984#pragma GCC diagnostic push
17985#pragma GCC diagnostic ignored "-Wfloat-equal"
17986#endif
17987 if (value == 0) // +-0
17988 {
17989 *first++ = '0';
17990 // Make it look like a floating-point number (#362, #378)
17991 *first++ = '.';
17992 *first++ = '0';
17993 return first;
17994 }
17995#ifdef __GNUC__
17996#pragma GCC diagnostic pop
17997#endif
17998
17999 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18000
18001 // Compute v = buffer * 10^decimal_exponent.
18002 // The decimal digits are stored in the buffer, which needs to be interpreted
18003 // as an unsigned decimal integer.
18004 // len is the length of the buffer, i.e. the number of decimal digits.
18005 int len = 0;
18006 int decimal_exponent = 0;
18007 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18008
18009 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18010
18011 // Format the buffer like printf("%.*g", prec, value)
18012 constexpr int kMinExp = -4;
18013 // Use digits10 here to increase compatibility with version 2.
18014 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18015
18016 JSON_ASSERT(last - first >= kMaxExp + 2);
18017 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18018 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18019
18020 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18021 }
18022
18023} // namespace detail
18025
18026// #include <nlohmann/detail/exceptions.hpp>
18027
18028// #include <nlohmann/detail/macro_scope.hpp>
18029
18030// #include <nlohmann/detail/meta/cpp_future.hpp>
18031
18032// #include <nlohmann/detail/output/binary_writer.hpp>
18033
18034// #include <nlohmann/detail/output/output_adapters.hpp>
18035
18036// #include <nlohmann/detail/string_concat.hpp>
18037
18038// #include <nlohmann/detail/value_t.hpp>
18039
18040
18042namespace detail
18043{
18044
18046 // serialization //
18048
18051 {
18052 strict,
18053 replace,
18054 ignore
18055 };
18056
18057 template<typename BasicJsonType>
18059 {
18060 using string_t = typename BasicJsonType::string_t;
18061 using number_float_t = typename BasicJsonType::number_float_t;
18062 using number_integer_t = typename BasicJsonType::number_integer_t;
18063 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18064 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18065 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18066 static constexpr std::uint8_t UTF8_REJECT = 1;
18067
18068 public:
18076 : o(std::move(s))
18077 , loc(std::localeconv())
18078 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->thousands_sep)))
18079 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->decimal_point)))
18080 , indent_char(ichar)
18082 , error_handler(error_handler_)
18083 {}
18084
18085 // delete because of pointer members
18086 serializer(const serializer&) = delete;
18090 ~serializer() = default;
18091
18114 void dump(const BasicJsonType& val,
18115 const bool pretty_print,
18116 const bool ensure_ascii,
18117 const unsigned int indent_step,
18118 const unsigned int current_indent = 0)
18119 {
18120 switch (val.m_data.m_type)
18121 {
18122 case value_t::object:
18123 {
18124 if (val.m_data.m_value.object->empty())
18125 {
18126 o->write_characters("{}", 2);
18127 return;
18128 }
18129
18130 if (pretty_print)
18131 {
18132 o->write_characters("{\n", 2);
18133
18134 // variable to hold indentation for recursive calls
18135 const auto new_indent = current_indent + indent_step;
18136 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18137 {
18138 indent_string.resize(indent_string.size() * 2, ' ');
18139 }
18140
18141 // first n-1 elements
18142 auto i = val.m_data.m_value.object->cbegin();
18143 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18144 {
18145 o->write_characters(indent_string.c_str(), new_indent);
18146 o->write_character('\"');
18147 dump_escaped(i->first, ensure_ascii);
18148 o->write_characters("\": ", 3);
18149 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18150 o->write_characters(",\n", 2);
18151 }
18152
18153 // last element
18154 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18155 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18156 o->write_characters(indent_string.c_str(), new_indent);
18157 o->write_character('\"');
18158 dump_escaped(i->first, ensure_ascii);
18159 o->write_characters("\": ", 3);
18160 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18161
18162 o->write_character('\n');
18163 o->write_characters(indent_string.c_str(), current_indent);
18164 o->write_character('}');
18165 }
18166 else
18167 {
18168 o->write_character('{');
18169
18170 // first n-1 elements
18171 auto i = val.m_data.m_value.object->cbegin();
18172 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18173 {
18174 o->write_character('\"');
18175 dump_escaped(i->first, ensure_ascii);
18176 o->write_characters("\":", 2);
18177 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18178 o->write_character(',');
18179 }
18180
18181 // last element
18182 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18183 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18184 o->write_character('\"');
18185 dump_escaped(i->first, ensure_ascii);
18186 o->write_characters("\":", 2);
18187 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18188
18189 o->write_character('}');
18190 }
18191
18192 return;
18193 }
18194
18195 case value_t::array:
18196 {
18197 if (val.m_data.m_value.array->empty())
18198 {
18199 o->write_characters("[]", 2);
18200 return;
18201 }
18202
18203 if (pretty_print)
18204 {
18205 o->write_characters("[\n", 2);
18206
18207 // variable to hold indentation for recursive calls
18208 const auto new_indent = current_indent + indent_step;
18209 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18210 {
18211 indent_string.resize(indent_string.size() * 2, ' ');
18212 }
18213
18214 // first n-1 elements
18215 for (auto i = val.m_data.m_value.array->cbegin();
18216 i != val.m_data.m_value.array->cend() - 1; ++i)
18217 {
18218 o->write_characters(indent_string.c_str(), new_indent);
18219 dump(*i, true, ensure_ascii, indent_step, new_indent);
18220 o->write_characters(",\n", 2);
18221 }
18222
18223 // last element
18224 JSON_ASSERT(!val.m_data.m_value.array->empty());
18225 o->write_characters(indent_string.c_str(), new_indent);
18226 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18227
18228 o->write_character('\n');
18229 o->write_characters(indent_string.c_str(), current_indent);
18230 o->write_character(']');
18231 }
18232 else
18233 {
18234 o->write_character('[');
18235
18236 // first n-1 elements
18237 for (auto i = val.m_data.m_value.array->cbegin();
18238 i != val.m_data.m_value.array->cend() - 1; ++i)
18239 {
18240 dump(*i, false, ensure_ascii, indent_step, current_indent);
18241 o->write_character(',');
18242 }
18243
18244 // last element
18245 JSON_ASSERT(!val.m_data.m_value.array->empty());
18246 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18247
18248 o->write_character(']');
18249 }
18250
18251 return;
18252 }
18253
18254 case value_t::string:
18255 {
18256 o->write_character('\"');
18257 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18258 o->write_character('\"');
18259 return;
18260 }
18261
18262 case value_t::binary:
18263 {
18264 if (pretty_print)
18265 {
18266 o->write_characters("{\n", 2);
18267
18268 // variable to hold indentation for recursive calls
18269 const auto new_indent = current_indent + indent_step;
18270 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18271 {
18272 indent_string.resize(indent_string.size() * 2, ' ');
18273 }
18274
18275 o->write_characters(indent_string.c_str(), new_indent);
18276
18277 o->write_characters("\"bytes\": [", 10);
18278
18279 if (!val.m_data.m_value.binary->empty())
18280 {
18281 for (auto i = val.m_data.m_value.binary->cbegin();
18282 i != val.m_data.m_value.binary->cend() - 1; ++i)
18283 {
18284 dump_integer(*i);
18285 o->write_characters(", ", 2);
18286 }
18287 dump_integer(val.m_data.m_value.binary->back());
18288 }
18289
18290 o->write_characters("],\n", 3);
18291 o->write_characters(indent_string.c_str(), new_indent);
18292
18293 o->write_characters("\"subtype\": ", 11);
18294 if (val.m_data.m_value.binary->has_subtype())
18295 {
18296 dump_integer(val.m_data.m_value.binary->subtype());
18297 }
18298 else
18299 {
18300 o->write_characters("null", 4);
18301 }
18302 o->write_character('\n');
18303 o->write_characters(indent_string.c_str(), current_indent);
18304 o->write_character('}');
18305 }
18306 else
18307 {
18308 o->write_characters("{\"bytes\":[", 10);
18309
18310 if (!val.m_data.m_value.binary->empty())
18311 {
18312 for (auto i = val.m_data.m_value.binary->cbegin();
18313 i != val.m_data.m_value.binary->cend() - 1; ++i)
18314 {
18315 dump_integer(*i);
18316 o->write_character(',');
18317 }
18318 dump_integer(val.m_data.m_value.binary->back());
18319 }
18320
18321 o->write_characters("],\"subtype\":", 12);
18322 if (val.m_data.m_value.binary->has_subtype())
18323 {
18324 dump_integer(val.m_data.m_value.binary->subtype());
18325 o->write_character('}');
18326 }
18327 else
18328 {
18329 o->write_characters("null}", 5);
18330 }
18331 }
18332 return;
18333 }
18334
18335 case value_t::boolean:
18336 {
18337 if (val.m_data.m_value.boolean)
18338 {
18339 o->write_characters("true", 4);
18340 }
18341 else
18342 {
18343 o->write_characters("false", 5);
18344 }
18345 return;
18346 }
18347
18349 {
18350 dump_integer(val.m_data.m_value.number_integer);
18351 return;
18352 }
18353
18355 {
18356 dump_integer(val.m_data.m_value.number_unsigned);
18357 return;
18358 }
18359
18361 {
18362 dump_float(val.m_data.m_value.number_float);
18363 return;
18364 }
18365
18366 case value_t::discarded:
18367 {
18368 o->write_characters("<discarded>", 11);
18369 return;
18370 }
18371
18372 case value_t::null:
18373 {
18374 o->write_characters("null", 4);
18375 return;
18376 }
18377
18378 default: // LCOV_EXCL_LINE
18379 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18380 }
18381 }
18382
18398 void dump_escaped(const string_t& s, const bool ensure_ascii)
18399 {
18400 std::uint32_t codepoint{};
18401 std::uint8_t state = UTF8_ACCEPT;
18402 std::size_t bytes = 0; // number of bytes written to string_buffer
18403
18404 // number of bytes written at the point of the last valid byte
18406 std::size_t undumped_chars = 0;
18407
18408 for (std::size_t i = 0; i < s.size(); ++i)
18409 {
18410 const auto byte = static_cast<std::uint8_t>(s[i]);
18411
18412 switch (decode(state, codepoint, byte))
18413 {
18414 case UTF8_ACCEPT: // decode found a new code point
18415 {
18416 switch (codepoint)
18417 {
18418 case 0x08: // backspace
18419 {
18420 string_buffer[bytes++] = '\\';
18421 string_buffer[bytes++] = 'b';
18422 break;
18423 }
18424
18425 case 0x09: // horizontal tab
18426 {
18427 string_buffer[bytes++] = '\\';
18428 string_buffer[bytes++] = 't';
18429 break;
18430 }
18431
18432 case 0x0A: // newline
18433 {
18434 string_buffer[bytes++] = '\\';
18435 string_buffer[bytes++] = 'n';
18436 break;
18437 }
18438
18439 case 0x0C: // formfeed
18440 {
18441 string_buffer[bytes++] = '\\';
18442 string_buffer[bytes++] = 'f';
18443 break;
18444 }
18445
18446 case 0x0D: // carriage return
18447 {
18448 string_buffer[bytes++] = '\\';
18449 string_buffer[bytes++] = 'r';
18450 break;
18451 }
18452
18453 case 0x22: // quotation mark
18454 {
18455 string_buffer[bytes++] = '\\';
18456 string_buffer[bytes++] = '\"';
18457 break;
18458 }
18459
18460 case 0x5C: // reverse solidus
18461 {
18462 string_buffer[bytes++] = '\\';
18463 string_buffer[bytes++] = '\\';
18464 break;
18465 }
18466
18467 default:
18468 {
18469 // escape control characters (0x00..0x1F) or, if
18470 // ensure_ascii parameter is used, non-ASCII characters
18471 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18472 {
18473 if (codepoint <= 0xFFFF)
18474 {
18475 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18476 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18477 static_cast<std::uint16_t>(codepoint)));
18478 bytes += 6;
18479 }
18480 else
18481 {
18482 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18483 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18484 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18485 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18486 bytes += 12;
18487 }
18488 }
18489 else
18490 {
18491 // copy byte to buffer (all previous bytes
18492 // been copied have in default case above)
18493 string_buffer[bytes++] = s[i];
18494 }
18495 break;
18496 }
18497 }
18498
18499 // write buffer and reset index; there must be 13 bytes
18500 // left, as this is the maximal number of bytes to be
18501 // written ("\uxxxx\uxxxx\0") for one code point
18502 if (string_buffer.size() - bytes < 13)
18503 {
18504 o->write_characters(string_buffer.data(), bytes);
18505 bytes = 0;
18506 }
18507
18508 // remember the byte position of this accept
18510 undumped_chars = 0;
18511 break;
18512 }
18513
18514 case UTF8_REJECT: // decode found invalid UTF-8 byte
18515 {
18516 switch (error_handler)
18517 {
18519 {
18520 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18521 }
18522
18525 {
18526 // in case we saw this character the first time, we
18527 // would like to read it again, because the byte
18528 // may be OK for itself, but just not OK for the
18529 // previous sequence
18530 if (undumped_chars > 0)
18531 {
18532 --i;
18533 }
18534
18535 // reset length buffer to the last accepted index;
18536 // thus removing/ignoring the invalid characters
18538
18540 {
18541 // add a replacement character
18542 if (ensure_ascii)
18543 {
18544 string_buffer[bytes++] = '\\';
18545 string_buffer[bytes++] = 'u';
18546 string_buffer[bytes++] = 'f';
18547 string_buffer[bytes++] = 'f';
18548 string_buffer[bytes++] = 'f';
18549 string_buffer[bytes++] = 'd';
18550 }
18551 else
18552 {
18556 }
18557
18558 // write buffer and reset index; there must be 13 bytes
18559 // left, as this is the maximal number of bytes to be
18560 // written ("\uxxxx\uxxxx\0") for one code point
18561 if (string_buffer.size() - bytes < 13)
18562 {
18563 o->write_characters(string_buffer.data(), bytes);
18564 bytes = 0;
18565 }
18566
18568 }
18569
18570 undumped_chars = 0;
18571
18572 // continue processing the string
18573 state = UTF8_ACCEPT;
18574 break;
18575 }
18576
18577 default: // LCOV_EXCL_LINE
18578 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18579 }
18580 break;
18581 }
18582
18583 default: // decode found yet incomplete multi-byte code point
18584 {
18585 if (!ensure_ascii)
18586 {
18587 // code point will not be escaped - copy byte to buffer
18588 string_buffer[bytes++] = s[i];
18589 }
18591 break;
18592 }
18593 }
18594 }
18595
18596 // we finished processing the string
18597 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18598 {
18599 // write buffer
18600 if (bytes > 0)
18601 {
18602 o->write_characters(string_buffer.data(), bytes);
18603 }
18604 }
18605 else
18606 {
18607 // we finish reading, but do not accept: string was incomplete
18608 switch (error_handler)
18609 {
18611 {
18612 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
18613 }
18614
18616 {
18617 // write all accepted bytes
18618 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18619 break;
18620 }
18621
18623 {
18624 // write all accepted bytes
18625 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18626 // add a replacement character
18627 if (ensure_ascii)
18628 {
18629 o->write_characters("\\ufffd", 6);
18630 }
18631 else
18632 {
18633 o->write_characters("\xEF\xBF\xBD", 3);
18634 }
18635 break;
18636 }
18637
18638 default: // LCOV_EXCL_LINE
18639 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18640 }
18641 }
18642 }
18643
18644 private:
18653 inline unsigned int count_digits(number_unsigned_t x) noexcept
18654 {
18655 unsigned int n_digits = 1;
18656 for (;;)
18657 {
18658 if (x < 10)
18659 {
18660 return n_digits;
18661 }
18662 if (x < 100)
18663 {
18664 return n_digits + 1;
18665 }
18666 if (x < 1000)
18667 {
18668 return n_digits + 2;
18669 }
18670 if (x < 10000)
18671 {
18672 return n_digits + 3;
18673 }
18674 x = x / 10000u;
18675 n_digits += 4;
18676 }
18677 }
18678
18684 static std::string hex_bytes(std::uint8_t byte)
18685 {
18686 std::string result = "FF";
18687 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18688 result[0] = nibble_to_hex[byte / 16];
18689 result[1] = nibble_to_hex[byte % 16];
18690 return result;
18691 }
18692
18693 // templates to avoid warnings about useless casts
18694 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18695 bool is_negative_number(NumberType x)
18696 {
18697 return x < 0;
18698 }
18699
18700 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18701 bool is_negative_number(NumberType /*unused*/)
18702 {
18703 return false;
18704 }
18705
18715 template < typename NumberType, detail::enable_if_t <
18716 std::is_integral<NumberType>::value ||
18717 std::is_same<NumberType, number_unsigned_t>::value ||
18718 std::is_same<NumberType, number_integer_t>::value ||
18719 std::is_same<NumberType, binary_char_t>::value,
18720 int > = 0 >
18721 void dump_integer(NumberType x)
18722 {
18723 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18724 {
18725 {
18726 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18727 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18728 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18729 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18730 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18731 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18732 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18733 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18734 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18735 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18736 }
18737 };
18738
18739 // special case for "0"
18740 if (x == 0)
18741 {
18742 o->write_character('0');
18743 return;
18744 }
18745
18746 // use a pointer to fill the buffer
18747 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18748
18749 number_unsigned_t abs_value;
18750
18751 unsigned int n_chars{};
18752
18753 if (is_negative_number(x))
18754 {
18755 *buffer_ptr = '-';
18756 abs_value = remove_sign(static_cast<number_integer_t>(x));
18757
18758 // account one more byte for the minus sign
18759 n_chars = 1 + count_digits(abs_value);
18760 }
18761 else
18762 {
18763 abs_value = static_cast<number_unsigned_t>(x);
18764 n_chars = count_digits(abs_value);
18765 }
18766
18767 // spare 1 byte for '\0'
18768 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18769
18770 // jump to the end to generate the string from backward,
18771 // so we later avoid reversing the result
18772 buffer_ptr += n_chars;
18773
18774 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18775 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18776 while (abs_value >= 100)
18777 {
18778 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18779 abs_value /= 100;
18780 *(--buffer_ptr) = digits_to_99[digits_index][1];
18781 *(--buffer_ptr) = digits_to_99[digits_index][0];
18782 }
18783
18784 if (abs_value >= 10)
18785 {
18786 const auto digits_index = static_cast<unsigned>(abs_value);
18787 *(--buffer_ptr) = digits_to_99[digits_index][1];
18788 *(--buffer_ptr) = digits_to_99[digits_index][0];
18789 }
18790 else
18791 {
18792 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18793 }
18794
18795 o->write_characters(number_buffer.data(), n_chars);
18796 }
18797
18806 void dump_float(number_float_t x)
18807 {
18808 // NaN / inf
18809 if (!std::isfinite(x))
18810 {
18811 o->write_characters("null", 4);
18812 return;
18813 }
18814
18815 // If number_float_t is an IEEE-754 single or double precision number,
18816 // use the Grisu2 algorithm to produce short numbers which are
18817 // guaranteed to round-trip, using strtof and strtod, resp.
18818 //
18819 // NB: The test below works if <long double> == <double>.
18820 static constexpr bool is_ieee_single_or_double
18821 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
18822 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
18823
18824 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18825 }
18826
18827 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18828 {
18829 auto* begin = number_buffer.data();
18830 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18831
18832 o->write_characters(begin, static_cast<size_t>(end - begin));
18833 }
18834
18835 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18836 {
18837 // get number of digits for a float -> text -> float round-trip
18838 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18839
18840 // the actual conversion
18841 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18842 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18843
18844 // negative value indicates an error
18845 JSON_ASSERT(len > 0);
18846 // check if buffer was large enough
18847 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18848
18849 // erase thousands separator
18850 if (thousands_sep != '\0')
18851 {
18852 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18853 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18854 std::fill(end, number_buffer.end(), '\0');
18855 JSON_ASSERT((end - number_buffer.begin()) <= len);
18856 len = (end - number_buffer.begin());
18857 }
18858
18859 // convert decimal point to '.'
18860 if (decimal_point != '\0' && decimal_point != '.')
18861 {
18862 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18863 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18864 if (dec_pos != number_buffer.end())
18865 {
18866 *dec_pos = '.';
18867 }
18868 }
18869
18870 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18871
18872 // determine if we need to append ".0"
18873 const bool value_is_int_like =
18874 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18875 [](char c)
18876 {
18877 return c == '.' || c == 'e';
18878 });
18879
18880 if (value_is_int_like)
18881 {
18882 o->write_characters(".0", 2);
18883 }
18884 }
18885
18907 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18908 {
18909 static const std::array<std::uint8_t, 400> utf8d =
18910 {
18911 {
18912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
18913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
18914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
18915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
18916 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
18917 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
18918 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
18919 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18920 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18921 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18922 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
18923 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
18924 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
18925 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
18926 }
18927 };
18928
18929 JSON_ASSERT(byte < utf8d.size());
18930 const std::uint8_t type = utf8d[byte];
18931
18932 codep = (state != UTF8_ACCEPT)
18933 ? (byte & 0x3fu) | (codep << 6u)
18934 : (0xFFu >> type) & (byte);
18935
18936 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18937 JSON_ASSERT(index < utf8d.size());
18938 state = utf8d[index];
18939 return state;
18940 }
18941
18942 /*
18943 * Overload to make the compiler happy while it is instantiating
18944 * dump_integer for number_unsigned_t.
18945 * Must never be called.
18946 */
18947 number_unsigned_t remove_sign(number_unsigned_t x)
18948 {
18949 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18950 return x; // LCOV_EXCL_LINE
18951 }
18952
18953 /*
18954 * Helper function for dump_integer
18955 *
18956 * This function takes a negative signed integer and returns its absolute
18957 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18958 * not directly remove the sign of an arbitrary signed integer as the
18959 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18960 * #1708 for details.
18961 */
18962 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18963 {
18964 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18965 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18966 }
18967
18968 private:
18970 output_adapter_t<char> o = nullptr;
18971
18973 std::array<char, 64> number_buffer{ {} };
18974
18976 const std::lconv* loc = nullptr;
18978 const char thousands_sep = '\0';
18980 const char decimal_point = '\0';
18981
18983 std::array<char, 512> string_buffer{ {} };
18984
18986 const char indent_char;
18989
18992 };
18993
18994} // namespace detail
18996
18997// #include <nlohmann/detail/value_t.hpp>
18998
18999// #include <nlohmann/json_fwd.hpp>
19000
19001// #include <nlohmann/ordered_map.hpp>
19002// __ _____ _____ _____
19003// __| | __| | | | JSON for Modern C++
19004// | | |__ | | | | | | version 3.11.3
19005// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19006//
19007// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
19008// SPDX-License-Identifier: MIT
19009
19010
19011
19012#include <functional> // equal_to, less
19013#include <initializer_list> // initializer_list
19014#include <iterator> // input_iterator_tag, iterator_traits
19015#include <memory> // allocator
19016#include <stdexcept> // for out_of_range
19017#include <type_traits> // enable_if, is_convertible
19018#include <utility> // pair
19019#include <vector> // vector
19020
19021// #include <nlohmann/detail/macro_scope.hpp>
19022
19023// #include <nlohmann/detail/meta/type_traits.hpp>
19024
19025
19027
19030template <class Key, class T, class IgnoredLess = std::less<Key>,
19031 class Allocator = std::allocator<std::pair<const Key, T>>>
19032struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19033{
19034 using key_type = Key;
19035 using mapped_type = T;
19036 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19037 using iterator = typename Container::iterator;
19038 using const_iterator = typename Container::const_iterator;
19039 using size_type = typename Container::size_type;
19040 using value_type = typename Container::value_type;
19041#ifdef JSON_HAS_CPP_14
19042 using key_compare = std::equal_to<>;
19043#else
19044 using key_compare = std::equal_to<Key>;
19045#endif
19046
19047 // Explicit constructors instead of `using Container::Container`
19048 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19049 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19050 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{ alloc } {}
19051 template <class It>
19052 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19053 : Container{ first, last, alloc } {}
19054 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator())
19055 : Container{ init, alloc } {}
19056
19057 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19058 {
19059 for (auto it = this->begin(); it != this->end(); ++it)
19060 {
19061 if (m_compare(it->first, key))
19062 {
19063 return { it, false };
19064 }
19065 }
19066 Container::emplace_back(key, std::forward<T>(t));
19067 return { std::prev(this->end()), true };
19068 }
19069
19070 template<class KeyType, detail::enable_if_t<
19072 std::pair<iterator, bool> emplace(KeyType&& key, T&& t)
19073 {
19074 for (auto it = this->begin(); it != this->end(); ++it)
19075 {
19076 if (m_compare(it->first, key))
19077 {
19078 return { it, false };
19079 }
19080 }
19081 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19082 return { std::prev(this->end()), true };
19083 }
19084
19085 T& operator[](const key_type& key)
19086 {
19087 return emplace(key, T{}).first->second;
19088 }
19089
19090 template<class KeyType, detail::enable_if_t<
19092 T& operator[](KeyType&& key)
19093 {
19094 return emplace(std::forward<KeyType>(key), T{}).first->second;
19095 }
19096
19097 const T& operator[](const key_type& key) const
19098 {
19099 return at(key);
19100 }
19101
19102 template<class KeyType, detail::enable_if_t<
19104 const T& operator[](KeyType&& key) const
19105 {
19106 return at(std::forward<KeyType>(key));
19107 }
19108
19109 T& at(const key_type& key)
19110 {
19111 for (auto it = this->begin(); it != this->end(); ++it)
19112 {
19113 if (m_compare(it->first, key))
19114 {
19115 return it->second;
19116 }
19117 }
19118
19119 JSON_THROW(std::out_of_range("key not found"));
19120 }
19121
19122 template<class KeyType, detail::enable_if_t<
19124 T& at(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
19125 {
19126 for (auto it = this->begin(); it != this->end(); ++it)
19127 {
19128 if (m_compare(it->first, key))
19129 {
19130 return it->second;
19131 }
19132 }
19133
19134 JSON_THROW(std::out_of_range("key not found"));
19135 }
19136
19137 const T& at(const key_type& key) const
19138 {
19139 for (auto it = this->begin(); it != this->end(); ++it)
19140 {
19141 if (m_compare(it->first, key))
19142 {
19143 return it->second;
19144 }
19145 }
19146
19147 JSON_THROW(std::out_of_range("key not found"));
19148 }
19149
19150 template<class KeyType, detail::enable_if_t<
19152 const T& at(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19153 {
19154 for (auto it = this->begin(); it != this->end(); ++it)
19155 {
19156 if (m_compare(it->first, key))
19157 {
19158 return it->second;
19159 }
19160 }
19161
19162 JSON_THROW(std::out_of_range("key not found"));
19163 }
19164
19166 {
19167 for (auto it = this->begin(); it != this->end(); ++it)
19168 {
19169 if (m_compare(it->first, key))
19170 {
19171 // Since we cannot move const Keys, re-construct them in place
19172 for (auto next = it; ++next != this->end(); ++it)
19173 {
19174 it->~value_type(); // Destroy but keep allocation
19175 new (&*it) value_type{ std::move(*next) };
19176 }
19177 Container::pop_back();
19178 return 1;
19179 }
19180 }
19181 return 0;
19182 }
19183
19184 template<class KeyType, detail::enable_if_t<
19186 size_type erase(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
19187 {
19188 for (auto it = this->begin(); it != this->end(); ++it)
19189 {
19190 if (m_compare(it->first, key))
19191 {
19192 // Since we cannot move const Keys, re-construct them in place
19193 for (auto next = it; ++next != this->end(); ++it)
19194 {
19195 it->~value_type(); // Destroy but keep allocation
19196 new (&*it) value_type{ std::move(*next) };
19197 }
19198 Container::pop_back();
19199 return 1;
19200 }
19201 }
19202 return 0;
19203 }
19204
19206 {
19207 return erase(pos, std::next(pos));
19208 }
19209
19211 {
19212 if (first == last)
19213 {
19214 return first;
19215 }
19216
19217 const auto elements_affected = std::distance(first, last);
19218 const auto offset = std::distance(Container::begin(), first);
19219
19220 // This is the start situation. We need to delete elements_affected
19221 // elements (3 in this example: e, f, g), and need to return an
19222 // iterator past the last deleted element (h in this example).
19223 // Note that offset is the distance from the start of the vector
19224 // to first. We will need this later.
19225
19226 // [ a, b, c, d, e, f, g, h, i, j ]
19227 // ^ ^
19228 // first last
19229
19230 // Since we cannot move const Keys, we re-construct them in place.
19231 // We start at first and re-construct (viz. copy) the elements from
19232 // the back of the vector. Example for first iteration:
19233
19234 // ,--------.
19235 // v | destroy e and re-construct with h
19236 // [ a, b, c, d, e, f, g, h, i, j ]
19237 // ^ ^
19238 // it it + elements_affected
19239
19240 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19241 {
19242 it->~value_type(); // destroy but keep allocation
19243 new (&*it) value_type{ std::move(*std::next(it, elements_affected)) }; // "move" next element to it
19244 }
19245
19246 // [ a, b, c, d, h, i, j, h, i, j ]
19247 // ^ ^
19248 // first last
19249
19250 // remove the unneeded elements at the end of the vector
19251 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19252
19253 // [ a, b, c, d, h, i, j ]
19254 // ^ ^
19255 // first last
19256
19257 // first is now pointing past the last deleted element, but we cannot
19258 // use this iterator, because it may have been invalidated by the
19259 // resize call. Instead, we can return begin() + offset.
19260 return Container::begin() + offset;
19261 }
19262
19263 size_type count(const key_type& key) const
19264 {
19265 for (auto it = this->begin(); it != this->end(); ++it)
19266 {
19267 if (m_compare(it->first, key))
19268 {
19269 return 1;
19270 }
19271 }
19272 return 0;
19273 }
19274
19275 template<class KeyType, detail::enable_if_t<
19277 size_type count(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19278 {
19279 for (auto it = this->begin(); it != this->end(); ++it)
19280 {
19281 if (m_compare(it->first, key))
19282 {
19283 return 1;
19284 }
19285 }
19286 return 0;
19287 }
19288
19290 {
19291 for (auto it = this->begin(); it != this->end(); ++it)
19292 {
19293 if (m_compare(it->first, key))
19294 {
19295 return it;
19296 }
19297 }
19298 return Container::end();
19299 }
19300
19301 template<class KeyType, detail::enable_if_t<
19303 iterator find(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
19304 {
19305 for (auto it = this->begin(); it != this->end(); ++it)
19306 {
19307 if (m_compare(it->first, key))
19308 {
19309 return it;
19310 }
19311 }
19312 return Container::end();
19313 }
19314
19315 const_iterator find(const key_type& key) const
19316 {
19317 for (auto it = this->begin(); it != this->end(); ++it)
19318 {
19319 if (m_compare(it->first, key))
19320 {
19321 return it;
19322 }
19323 }
19324 return Container::end();
19325 }
19326
19327 std::pair<iterator, bool> insert(value_type&& value)
19328 {
19329 return emplace(value.first, std::move(value.second));
19330 }
19331
19332 std::pair<iterator, bool> insert(const value_type& value)
19333 {
19334 for (auto it = this->begin(); it != this->end(); ++it)
19335 {
19336 if (m_compare(it->first, value.first))
19337 {
19338 return { it, false };
19339 }
19340 }
19341 Container::push_back(value);
19342 return { --this->end(), true };
19343 }
19344
19345 template<typename InputIt>
19346 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19347 std::input_iterator_tag>::value>::type;
19348
19349 template<typename InputIt, typename = require_input_iter<InputIt>>
19350 void insert(InputIt first, InputIt last)
19351 {
19352 for (auto it = first; it != last; ++it)
19353 {
19354 insert(*it);
19355 }
19356 }
19357
19358private:
19360};
19361
19363
19364
19365#if defined(JSON_HAS_CPP_17)
19366#if JSON_HAS_STATIC_RTTI
19367#include <any>
19368#endif
19369#include <string_view>
19370#endif
19371
19378
19398class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19399 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19400{
19401private:
19402 template<detail::value_t> friend struct detail::external_constructor;
19403
19404 template<typename>
19405 friend class ::nlohmann::json_pointer;
19406 // can be restored when json_pointer backwards compatibility is removed
19407 // friend ::nlohmann::json_pointer<StringType>;
19408
19409 template<typename BasicJsonType, typename InputType>
19410 friend class ::nlohmann::detail::parser;
19411 friend ::nlohmann::detail::serializer<basic_json>;
19412 template<typename BasicJsonType>
19413 friend class ::nlohmann::detail::iter_impl;
19414 template<typename BasicJsonType, typename CharType>
19415 friend class ::nlohmann::detail::binary_writer;
19416 template<typename BasicJsonType, typename InputType, typename SAX>
19417 friend class ::nlohmann::detail::binary_reader;
19418 template<typename BasicJsonType>
19419 friend class ::nlohmann::detail::json_sax_dom_parser;
19420 template<typename BasicJsonType>
19421 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19422 friend class ::nlohmann::detail::exception;
19423
19425 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19426 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19427
19429 // convenience aliases for types residing in namespace detail;
19430 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19431
19432 template<typename InputAdapterType>
19433 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19434 InputAdapterType adapter,
19436 const bool allow_exceptions = true,
19437 const bool ignore_comments = false
19438 )
19439 {
19440 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19441 std::move(cb), allow_exceptions, ignore_comments);
19442 }
19443
19444private:
19445 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19446 template<typename BasicJsonType>
19447 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19448 template<typename BasicJsonType>
19449 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19450 template<typename Iterator>
19451 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19452 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19453
19454 template<typename CharType>
19455 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19456
19457 template<typename InputType>
19458 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19459 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19460
19462 using serializer = ::nlohmann::detail::serializer<basic_json>;
19463
19464public:
19467 using json_pointer = ::nlohmann::json_pointer<StringType>;
19468 template<typename T, typename SFINAE>
19469 using json_serializer = JSONSerializer<T, SFINAE>;
19475 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19476
19480
19482 // exceptions //
19484
19488
19495
19497
19499 // container types //
19501
19506
19509
19514
19516 using difference_type = std::ptrdiff_t;
19518 using size_type = std::size_t;
19519
19521 using allocator_type = AllocatorType<basic_json>;
19522
19524 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19526 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19527
19529 using iterator = iter_impl<basic_json>;
19531 using const_iterator = iter_impl<const basic_json>;
19533 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19535 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19536
19538
19542 {
19543 return allocator_type();
19544 }
19545
19550 {
19551 basic_json result;
19552
19553 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19554 result["name"] = "JSON for Modern C++";
19555 result["url"] = "https://github.com/nlohmann/json";
19556 result["version"]["string"] =
19557 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19558 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19559 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19560 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19561 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19562 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19563
19564#ifdef _WIN32
19565 result["platform"] = "win32";
19566#elif defined __linux__
19567 result["platform"] = "linux";
19568#elif defined __APPLE__
19569 result["platform"] = "apple";
19570#elif defined __unix__
19571 result["platform"] = "unix";
19572#else
19573 result["platform"] = "unknown";
19574#endif
19575
19576#if defined(__ICC) || defined(__INTEL_COMPILER)
19577 result["compiler"] = { {"family", "icc"}, {"version", __INTEL_COMPILER} };
19578#elif defined(__clang__)
19579 result["compiler"] = { {"family", "clang"}, {"version", __clang_version__} };
19580#elif defined(__GNUC__) || defined(__GNUG__)
19581 result["compiler"] = { {"family", "gcc"}, {"version", detail::concat(
19582 std::to_string(__GNUC__), '.',
19583 std::to_string(__GNUC_MINOR__), '.',
19584 std::to_string(__GNUC_PATCHLEVEL__))
19585 }
19586 };
19587#elif defined(__HP_cc) || defined(__HP_aCC)
19588 result["compiler"] = "hp"
19589#elif defined(__IBMCPP__)
19590 result["compiler"] = { {"family", "ilecpp"}, {"version", __IBMCPP__} };
19591#elif defined(_MSC_VER)
19592 result["compiler"] = { {"family", "msvc"}, {"version", _MSC_VER} };
19593#elif defined(__PGI)
19594 result["compiler"] = { {"family", "pgcpp"}, {"version", __PGI} };
19595#elif defined(__SUNPRO_CC)
19596 result["compiler"] = { {"family", "sunpro"}, {"version", __SUNPRO_CC} };
19597#else
19598 result["compiler"] = { {"family", "unknown"}, {"version", "unknown"} };
19599#endif
19600
19601#if defined(_MSVC_LANG)
19602 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19603#elif defined(__cplusplus)
19604 result["compiler"]["c++"] = std::to_string(__cplusplus);
19605#else
19606 result["compiler"]["c++"] = "unknown";
19607#endif
19608 return result;
19609 }
19610
19612 // JSON value data types //
19614
19619
19624#if defined(JSON_HAS_CPP_14)
19625 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19626 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19627 using default_object_comparator_t = std::less<>;
19628#else
19629 using default_object_comparator_t = std::less<StringType>;
19630#endif
19631
19634 using object_t = ObjectType<StringType,
19635 basic_json,
19637 AllocatorType<std::pair<const StringType,
19638 basic_json>>>;
19639
19642 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19643
19646 using string_t = StringType;
19647
19650 using boolean_t = BooleanType;
19651
19654 using number_integer_t = NumberIntegerType;
19655
19658 using number_unsigned_t = NumberUnsignedType;
19659
19662 using number_float_t = NumberFloatType;
19663
19666 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19667
19671
19673
19674private:
19675
19677 template<typename T, typename... Args>
19679 static T* create(Args&& ... args)
19680 {
19681 AllocatorType<T> alloc;
19682 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19683
19684 auto deleter = [&](T* obj)
19685 {
19686 AllocatorTraits::deallocate(alloc, obj, 1);
19687 };
19688 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19689 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19690 JSON_ASSERT(obj != nullptr);
19691 return obj.release();
19692 }
19693
19695 // JSON value storage //
19697
19724 union json_value
19725 {
19729 array_t* array;
19731 string_t* string;
19733 binary_t* binary;
19735 boolean_t boolean;
19737 number_integer_t number_integer;
19739 number_unsigned_t number_unsigned;
19741 number_float_t number_float;
19742
19744 json_value() = default;
19746 json_value(boolean_t v) noexcept : boolean(v) {}
19748 json_value(number_integer_t v) noexcept : number_integer(v) {}
19750 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19752 json_value(number_float_t v) noexcept : number_float(v) {}
19754 json_value(value_t t)
19755 {
19756 switch (t)
19757 {
19758 case value_t::object:
19759 {
19760 object = create<object_t>();
19761 break;
19762 }
19763
19764 case value_t::array:
19765 {
19766 array = create<array_t>();
19767 break;
19768 }
19769
19770 case value_t::string:
19771 {
19772 string = create<string_t>("");
19773 break;
19774 }
19775
19776 case value_t::binary:
19777 {
19778 binary = create<binary_t>();
19779 break;
19780 }
19781
19782 case value_t::boolean:
19783 {
19784 boolean = static_cast<boolean_t>(false);
19785 break;
19786 }
19787
19788 case value_t::number_integer:
19789 {
19790 number_integer = static_cast<number_integer_t>(0);
19791 break;
19792 }
19793
19794 case value_t::number_unsigned:
19795 {
19796 number_unsigned = static_cast<number_unsigned_t>(0);
19797 break;
19798 }
19799
19800 case value_t::number_float:
19801 {
19802 number_float = static_cast<number_float_t>(0.0);
19803 break;
19804 }
19805
19806 case value_t::null:
19807 {
19808 object = nullptr; // silence warning, see #821
19809 break;
19810 }
19811
19812 case value_t::discarded:
19813 default:
19814 {
19815 object = nullptr; // silence warning, see #821
19816 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19817 {
19818 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
19819 }
19820 break;
19821 }
19822 }
19823 }
19824
19826 json_value(const string_t& value) : string(create<string_t>(value)) {}
19827
19829 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19830
19832 json_value(const object_t& value) : object(create<object_t>(value)) {}
19833
19835 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19836
19838 json_value(const array_t& value) : array(create<array_t>(value)) {}
19839
19841 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19842
19844 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19845
19847 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19848
19850 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19851
19853 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19854
19855 void destroy(value_t t)
19856 {
19857 if (
19858 (t == value_t::object && object == nullptr) ||
19859 (t == value_t::array && array == nullptr) ||
19860 (t == value_t::string && string == nullptr) ||
19861 (t == value_t::binary && binary == nullptr)
19862 )
19863 {
19864 //not initialized (e.g. due to exception in the ctor)
19865 return;
19866 }
19867 if (t == value_t::array || t == value_t::object)
19868 {
19869 // flatten the current json_value to a heap-allocated stack
19870 std::vector<basic_json> stack;
19871
19872 // move the top-level items to stack
19873 if (t == value_t::array)
19874 {
19875 stack.reserve(array->size());
19876 std::move(array->begin(), array->end(), std::back_inserter(stack));
19877 }
19878 else
19879 {
19880 stack.reserve(object->size());
19881 for (auto&& it : *object)
19882 {
19883 stack.push_back(std::move(it.second));
19884 }
19885 }
19886
19887 while (!stack.empty())
19888 {
19889 // move the last item to local variable to be processed
19890 basic_json current_item(std::move(stack.back()));
19891 stack.pop_back();
19892
19893 // if current_item is array/object, move
19894 // its children to the stack to be processed later
19895 if (current_item.is_array())
19896 {
19897 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19898
19899 current_item.m_data.m_value.array->clear();
19900 }
19901 else if (current_item.is_object())
19902 {
19903 for (auto&& it : *current_item.m_data.m_value.object)
19904 {
19905 stack.push_back(std::move(it.second));
19906 }
19907
19908 current_item.m_data.m_value.object->clear();
19909 }
19910
19911 // it's now safe that current_item get destructed
19912 // since it doesn't have any children
19913 }
19914 }
19915
19916 switch (t)
19917 {
19918 case value_t::object:
19919 {
19920 AllocatorType<object_t> alloc;
19921 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19922 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19923 break;
19924 }
19925
19926 case value_t::array:
19927 {
19928 AllocatorType<array_t> alloc;
19929 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19930 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19931 break;
19932 }
19933
19934 case value_t::string:
19935 {
19936 AllocatorType<string_t> alloc;
19937 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19938 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19939 break;
19940 }
19941
19942 case value_t::binary:
19943 {
19944 AllocatorType<binary_t> alloc;
19945 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19946 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19947 break;
19948 }
19949
19950 case value_t::null:
19951 case value_t::boolean:
19952 case value_t::number_integer:
19953 case value_t::number_unsigned:
19954 case value_t::number_float:
19955 case value_t::discarded:
19956 default:
19957 {
19958 break;
19959 }
19960 }
19961 }
19962 };
19963
19964private:
19983 void assert_invariant(bool check_parents = true) const noexcept
19984 {
19985 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
19986 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
19987 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
19988 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
19989
19990#if JSON_DIAGNOSTICS
19991 JSON_TRY
19992 {
19993 // cppcheck-suppress assertWithSideEffect
19994 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json& j)
19995 {
19996 return j.m_parent == this;
19997 }));
19998 }
19999 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20000#endif
20001 static_cast<void>(check_parents);
20002 }
20003
20004 void set_parents()
20005 {
20006#if JSON_DIAGNOSTICS
20007 switch (m_data.m_type)
20008 {
20009 case value_t::array:
20010 {
20011 for (auto& element : *m_data.m_value.array)
20012 {
20013 element.m_parent = this;
20014 }
20015 break;
20016 }
20017
20018 case value_t::object:
20019 {
20020 for (auto& element : *m_data.m_value.object)
20021 {
20022 element.second.m_parent = this;
20023 }
20024 break;
20025 }
20026
20027 case value_t::null:
20028 case value_t::string:
20029 case value_t::boolean:
20030 case value_t::number_integer:
20031 case value_t::number_unsigned:
20032 case value_t::number_float:
20033 case value_t::binary:
20034 case value_t::discarded:
20035 default:
20036 break;
20037 }
20038#endif
20039 }
20040
20041 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20042 {
20043#if JSON_DIAGNOSTICS
20044 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20045 {
20046 (it + i)->m_parent = this;
20047 }
20048#else
20049 static_cast<void>(count_set_parents);
20050#endif
20051 return it;
20052 }
20053
20054 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20055 {
20056#if JSON_DIAGNOSTICS
20057 if (old_capacity != static_cast<std::size_t>(-1))
20058 {
20059 // see https://github.com/nlohmann/json/issues/2838
20060 JSON_ASSERT(type() == value_t::array);
20061 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20062 {
20063 // capacity has changed: update all parents
20064 set_parents();
20065 return j;
20066 }
20067 }
20068
20069 // ordered_json uses a vector internally, so pointers could have
20070 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20071#ifdef JSON_HEDLEY_MSVC_VERSION
20072#pragma warning(push )
20073#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20074#endif
20076 {
20077 set_parents();
20078 return j;
20079 }
20080#ifdef JSON_HEDLEY_MSVC_VERSION
20081#pragma warning( pop )
20082#endif
20083
20084 j.m_parent = this;
20085#else
20086 static_cast<void>(j);
20087 static_cast<void>(old_capacity);
20088#endif
20089 return j;
20090 }
20091
20092public:
20094 // JSON parser callback //
20096
20100
20104
20106 // constructors //
20108
20113
20117 : m_data(v)
20118 {
20119 assert_invariant();
20120 }
20121
20124 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20125 : basic_json(value_t::null)
20126 {
20127 assert_invariant();
20128 }
20129
20132 template < typename CompatibleType,
20136 basic_json(CompatibleType&& val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20137 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20138 std::forward<CompatibleType>(val))))
20139 {
20140 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20141 set_parents();
20142 assert_invariant();
20143 }
20144
20147 template < typename BasicJsonType,
20149 detail::is_basic_json<BasicJsonType>::value && !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20150 basic_json(const BasicJsonType& val)
20151 {
20152 using other_boolean_t = typename BasicJsonType::boolean_t;
20153 using other_number_float_t = typename BasicJsonType::number_float_t;
20154 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20155 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20156 using other_string_t = typename BasicJsonType::string_t;
20157 using other_object_t = typename BasicJsonType::object_t;
20158 using other_array_t = typename BasicJsonType::array_t;
20159 using other_binary_t = typename BasicJsonType::binary_t;
20160
20161 switch (val.type())
20162 {
20163 case value_t::boolean:
20164 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20165 break;
20166 case value_t::number_float:
20167 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20168 break;
20169 case value_t::number_integer:
20170 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20171 break;
20172 case value_t::number_unsigned:
20173 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20174 break;
20175 case value_t::string:
20176 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20177 break;
20178 case value_t::object:
20179 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20180 break;
20181 case value_t::array:
20182 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20183 break;
20184 case value_t::binary:
20185 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20186 break;
20187 case value_t::null:
20188 *this = nullptr;
20189 break;
20190 case value_t::discarded:
20191 m_data.m_type = value_t::discarded;
20192 break;
20193 default: // LCOV_EXCL_LINE
20194 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20195 }
20196 JSON_ASSERT(m_data.m_type == val.type());
20197 set_parents();
20198 assert_invariant();
20199 }
20200
20204 bool type_deduction = true,
20205 value_t manual_type = value_t::array)
20206 {
20207 // check if each element is an array with two elements whose first
20208 // element is a string
20209 bool is_an_object = std::all_of(init.begin(), init.end(),
20210 [](const detail::json_ref<basic_json>& element_ref)
20211 {
20212 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20213 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20214 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20215 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20216 });
20217
20218 // adjust type if type deduction is not wanted
20219 if (!type_deduction)
20220 {
20221 // if array is wanted, do not create an object though possible
20222 if (manual_type == value_t::array)
20223 {
20224 is_an_object = false;
20225 }
20226
20227 // if object is wanted but impossible, throw an exception
20228 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20229 {
20230 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20231 }
20232 }
20233
20234 if (is_an_object)
20235 {
20236 // the initializer list is a list of pairs -> create object
20237 m_data.m_type = value_t::object;
20238 m_data.m_value = value_t::object;
20239
20240 for (auto& element_ref : init)
20241 {
20242 auto element = element_ref.moved_or_copied();
20243 m_data.m_value.object->emplace(
20244 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20245 std::move((*element.m_data.m_value.array)[1]));
20246 }
20247 }
20248 else
20249 {
20250 // the initializer list describes an array -> create array
20251 m_data.m_type = value_t::array;
20252 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20253 }
20254
20255 set_parents();
20256 assert_invariant();
20257 }
20258
20262 static basic_json binary(const typename binary_t::container_type& init)
20263 {
20264 auto res = basic_json();
20265 res.m_data.m_type = value_t::binary;
20266 res.m_data.m_value = init;
20267 return res;
20268 }
20269
20273 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20274 {
20275 auto res = basic_json();
20276 res.m_data.m_type = value_t::binary;
20277 res.m_data.m_value = binary_t(init, subtype);
20278 return res;
20279 }
20280
20284 static basic_json binary(typename binary_t::container_type&& init)
20285 {
20286 auto res = basic_json();
20287 res.m_data.m_type = value_t::binary;
20288 res.m_data.m_value = std::move(init);
20289 return res;
20290 }
20291
20295 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20296 {
20297 auto res = basic_json();
20298 res.m_data.m_type = value_t::binary;
20299 res.m_data.m_value = binary_t(std::move(init), subtype);
20300 return res;
20301 }
20302
20307 {
20308 return basic_json(init, false, value_t::array);
20309 }
20310
20315 {
20316 return basic_json(init, false, value_t::object);
20317 }
20318
20322 m_data{ cnt, val }
20323 {
20324 set_parents();
20325 assert_invariant();
20326 }
20327
20330 template < class InputIT, typename std::enable_if <
20331 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20332 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20333 basic_json(InputIT first, InputIT last)
20334 {
20335 JSON_ASSERT(first.m_object != nullptr);
20336 JSON_ASSERT(last.m_object != nullptr);
20337
20338 // make sure iterator fits the current value
20339 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20340 {
20341 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20342 }
20343
20344 // copy type from first iterator
20345 m_data.m_type = first.m_object->m_data.m_type;
20346
20347 // check if iterator range is complete for primitive values
20348 switch (m_data.m_type)
20349 {
20350 case value_t::boolean:
20351 case value_t::number_float:
20352 case value_t::number_integer:
20353 case value_t::number_unsigned:
20354 case value_t::string:
20355 {
20356 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20357 || !last.m_it.primitive_iterator.is_end()))
20358 {
20359 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20360 }
20361 break;
20362 }
20363
20364 case value_t::null:
20365 case value_t::object:
20366 case value_t::array:
20367 case value_t::binary:
20368 case value_t::discarded:
20369 default:
20370 break;
20371 }
20372
20373 switch (m_data.m_type)
20374 {
20375 case value_t::number_integer:
20376 {
20377 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20378 break;
20379 }
20380
20381 case value_t::number_unsigned:
20382 {
20383 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20384 break;
20385 }
20386
20387 case value_t::number_float:
20388 {
20389 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20390 break;
20391 }
20392
20393 case value_t::boolean:
20394 {
20395 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20396 break;
20397 }
20398
20399 case value_t::string:
20400 {
20401 m_data.m_value = *first.m_object->m_data.m_value.string;
20402 break;
20403 }
20404
20405 case value_t::object:
20406 {
20407 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20408 last.m_it.object_iterator);
20409 break;
20410 }
20411
20412 case value_t::array:
20413 {
20414 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20415 last.m_it.array_iterator);
20416 break;
20417 }
20418
20419 case value_t::binary:
20420 {
20421 m_data.m_value = *first.m_object->m_data.m_value.binary;
20422 break;
20423 }
20424
20425 case value_t::null:
20426 case value_t::discarded:
20427 default:
20428 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20429 }
20430
20431 set_parents();
20432 assert_invariant();
20433 }
20434
20436 // other constructors and destructor //
20438
20439 template<typename JsonRef,
20441 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20442 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20443
20447 : json_base_class_t(other)
20448 {
20449 m_data.m_type = other.m_data.m_type;
20450 // check of passed value is valid
20451 other.assert_invariant();
20452
20453 switch (m_data.m_type)
20454 {
20455 case value_t::object:
20456 {
20457 m_data.m_value = *other.m_data.m_value.object;
20458 break;
20459 }
20460
20461 case value_t::array:
20462 {
20463 m_data.m_value = *other.m_data.m_value.array;
20464 break;
20465 }
20466
20467 case value_t::string:
20468 {
20469 m_data.m_value = *other.m_data.m_value.string;
20470 break;
20471 }
20472
20473 case value_t::boolean:
20474 {
20475 m_data.m_value = other.m_data.m_value.boolean;
20476 break;
20477 }
20478
20479 case value_t::number_integer:
20480 {
20481 m_data.m_value = other.m_data.m_value.number_integer;
20482 break;
20483 }
20484
20485 case value_t::number_unsigned:
20486 {
20487 m_data.m_value = other.m_data.m_value.number_unsigned;
20488 break;
20489 }
20490
20491 case value_t::number_float:
20492 {
20493 m_data.m_value = other.m_data.m_value.number_float;
20494 break;
20495 }
20496
20497 case value_t::binary:
20498 {
20499 m_data.m_value = *other.m_data.m_value.binary;
20500 break;
20501 }
20502
20503 case value_t::null:
20504 case value_t::discarded:
20505 default:
20506 break;
20507 }
20508
20509 set_parents();
20510 assert_invariant();
20511 }
20512
20515 basic_json(basic_json&& other) noexcept
20516 : json_base_class_t(std::forward<json_base_class_t>(other)),
20517 m_data(std::move(other.m_data))
20518 {
20519 // check that passed value is valid
20520 other.assert_invariant(false);
20521
20522 // invalidate payload
20523 other.m_data.m_type = value_t::null;
20524 other.m_data.m_value = {};
20525
20526 set_parents();
20527 assert_invariant();
20528 }
20529
20533 std::is_nothrow_move_constructible<value_t>::value&&
20534 std::is_nothrow_move_assignable<value_t>::value&&
20535 std::is_nothrow_move_constructible<json_value>::value&&
20536 std::is_nothrow_move_assignable<json_value>::value&&
20537 std::is_nothrow_move_assignable<json_base_class_t>::value
20538 )
20539 {
20540 // check that passed value is valid
20541 other.assert_invariant();
20542
20543 using std::swap;
20544 swap(m_data.m_type, other.m_data.m_type);
20545 swap(m_data.m_value, other.m_data.m_value);
20546 json_base_class_t::operator=(std::move(other));
20547
20548 set_parents();
20549 assert_invariant();
20550 return *this;
20551 }
20552
20555 ~basic_json() noexcept
20556 {
20557 assert_invariant(false);
20558 }
20559
20561
20562public:
20564 // object inspection //
20566
20570
20573 string_t dump(const int indent = -1,
20574 const char indent_char = ' ',
20575 const bool ensure_ascii = false,
20576 const error_handler_t error_handler = error_handler_t::strict) const
20577 {
20578 string_t result;
20579 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20580
20581 if (indent >= 0)
20582 {
20583 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20584 }
20585 else
20586 {
20587 s.dump(*this, false, ensure_ascii, 0);
20588 }
20589
20590 return result;
20591 }
20592
20595 constexpr value_t type() const noexcept
20596 {
20597 return m_data.m_type;
20598 }
20599
20602 constexpr bool is_primitive() const noexcept
20603 {
20604 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20605 }
20606
20609 constexpr bool is_structured() const noexcept
20610 {
20611 return is_array() || is_object();
20612 }
20613
20616 constexpr bool is_null() const noexcept
20617 {
20618 return m_data.m_type == value_t::null;
20619 }
20620
20623 constexpr bool is_boolean() const noexcept
20624 {
20625 return m_data.m_type == value_t::boolean;
20626 }
20627
20630 constexpr bool is_number() const noexcept
20631 {
20632 return is_number_integer() || is_number_float();
20633 }
20634
20637 constexpr bool is_number_integer() const noexcept
20638 {
20639 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20640 }
20641
20644 constexpr bool is_number_unsigned() const noexcept
20645 {
20646 return m_data.m_type == value_t::number_unsigned;
20647 }
20648
20651 constexpr bool is_number_float() const noexcept
20652 {
20653 return m_data.m_type == value_t::number_float;
20654 }
20655
20658 constexpr bool is_object() const noexcept
20659 {
20660 return m_data.m_type == value_t::object;
20661 }
20662
20665 constexpr bool is_array() const noexcept
20666 {
20667 return m_data.m_type == value_t::array;
20668 }
20669
20672 constexpr bool is_string() const noexcept
20673 {
20674 return m_data.m_type == value_t::string;
20675 }
20676
20679 constexpr bool is_binary() const noexcept
20680 {
20681 return m_data.m_type == value_t::binary;
20682 }
20683
20686 constexpr bool is_discarded() const noexcept
20687 {
20688 return m_data.m_type == value_t::discarded;
20689 }
20690
20693 constexpr operator value_t() const noexcept
20694 {
20695 return m_data.m_type;
20696 }
20697
20699
20700private:
20702 // value access //
20704
20706 boolean_t get_impl(boolean_t* /*unused*/) const
20707 {
20708 if (JSON_HEDLEY_LIKELY(is_boolean()))
20709 {
20710 return m_data.m_value.boolean;
20711 }
20712
20713 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20714 }
20715
20717 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20718 {
20719 return is_object() ? m_data.m_value.object : nullptr;
20720 }
20721
20723 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20724 {
20725 return is_object() ? m_data.m_value.object : nullptr;
20726 }
20727
20729 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20730 {
20731 return is_array() ? m_data.m_value.array : nullptr;
20732 }
20733
20735 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20736 {
20737 return is_array() ? m_data.m_value.array : nullptr;
20738 }
20739
20741 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20742 {
20743 return is_string() ? m_data.m_value.string : nullptr;
20744 }
20745
20747 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20748 {
20749 return is_string() ? m_data.m_value.string : nullptr;
20750 }
20751
20753 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20754 {
20755 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20756 }
20757
20759 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20760 {
20761 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20762 }
20763
20765 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20766 {
20767 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20768 }
20769
20771 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20772 {
20773 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20774 }
20775
20777 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20778 {
20779 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20780 }
20781
20783 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20784 {
20785 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20786 }
20787
20789 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20790 {
20791 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20792 }
20793
20795 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20796 {
20797 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20798 }
20799
20801 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20802 {
20803 return is_binary() ? m_data.m_value.binary : nullptr;
20804 }
20805
20807 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20808 {
20809 return is_binary() ? m_data.m_value.binary : nullptr;
20810 }
20811
20823 template<typename ReferenceType, typename ThisType>
20824 static ReferenceType get_ref_impl(ThisType& obj)
20825 {
20826 // delegate the call to get_ptr<>()
20827 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20828
20829 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20830 {
20831 return *ptr;
20832 }
20833
20834 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20835 }
20836
20837public:
20841
20844 template<typename PointerType, typename std::enable_if<
20845 std::is_pointer<PointerType>::value, int>::type = 0>
20846 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20847 {
20848 // delegate the call to get_impl_ptr<>()
20849 return get_impl_ptr(static_cast<PointerType>(nullptr));
20850 }
20851
20854 template < typename PointerType, typename std::enable_if <
20855 std::is_pointer<PointerType>::value&&
20856 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20857 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20858 {
20859 // delegate the call to get_impl_ptr<>() const
20860 return get_impl_ptr(static_cast<PointerType>(nullptr));
20861 }
20862
20863private:
20902 template < typename ValueType,
20906 int > = 0 >
20907 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20908 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20909 {
20910 auto ret = ValueType();
20911 JSONSerializer<ValueType>::from_json(*this, ret);
20912 return ret;
20913 }
20914
20945 template < typename ValueType,
20948 int > = 0 >
20949 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20950 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20951 {
20952 return JSONSerializer<ValueType>::from_json(*this);
20953 }
20954
20970 template < typename BasicJsonType,
20973 int > = 0 >
20974 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20975 {
20976 return *this;
20977 }
20978
20993 template<typename BasicJsonType,
20995 std::is_same<BasicJsonType, basic_json_t>::value,
20996 int> = 0>
20997 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
20998 {
20999 return *this;
21000 }
21001
21006 template<typename PointerType,
21008 std::is_pointer<PointerType>::value,
21009 int> = 0>
21010 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21011 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21012 {
21013 // delegate the call to get_ptr
21014 return get_ptr<PointerType>();
21015 }
21016
21017public:
21041 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21042#if defined(JSON_HAS_CPP_14)
21043 constexpr
21044#endif
21045 auto get() const noexcept(
21046 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21047 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21048 {
21049 // we cannot static_assert on ValueTypeCV being non-const, because
21050 // there is support for get<const basic_json_t>(), which is why we
21051 // still need the uncvref
21052 static_assert(!std::is_reference<ValueTypeCV>::value,
21053 "get() cannot be used with reference types, you might want to use get_ref()");
21054 return get_impl<ValueType>(detail::priority_tag<4> {});
21055 }
21056
21084 template<typename PointerType, typename std::enable_if<
21085 std::is_pointer<PointerType>::value, int>::type = 0>
21086 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21087 {
21088 // delegate the call to get_ptr
21089 return get_ptr<PointerType>();
21090 }
21091
21094 template < typename ValueType,
21098 int > = 0 >
21099 ValueType& get_to(ValueType& v) const noexcept(noexcept(
21100 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21101 {
21102 JSONSerializer<ValueType>::from_json(*this, v);
21103 return v;
21104 }
21105
21106 // specialization to allow calling get_to with a basic_json value
21107 // see https://github.com/nlohmann/json/issues/2175
21108 template<typename ValueType,
21111 int> = 0>
21112 ValueType& get_to(ValueType& v) const
21113 {
21114 v = *this;
21115 return v;
21116 }
21117
21118 template <
21119 typename T, std::size_t N,
21120 typename Array = T(&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21123 Array get_to(T(&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21124 noexcept(noexcept(JSONSerializer<Array>::from_json(
21125 std::declval<const basic_json_t&>(), v)))
21126 {
21127 JSONSerializer<Array>::from_json(*this, v);
21128 return v;
21129 }
21130
21133 template<typename ReferenceType, typename std::enable_if<
21134 std::is_reference<ReferenceType>::value, int>::type = 0>
21135 ReferenceType get_ref()
21136 {
21137 // delegate call to get_ref_impl
21138 return get_ref_impl<ReferenceType>(*this);
21139 }
21140
21143 template < typename ReferenceType, typename std::enable_if <
21144 std::is_reference<ReferenceType>::value&&
21145 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21146 ReferenceType get_ref() const
21147 {
21148 // delegate call to get_ref_impl
21149 return get_ref_impl<ReferenceType>(*this);
21150 }
21151
21181 template < typename ValueType, typename std::enable_if <
21189#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21191#endif
21192#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21194#endif
21196 >::value, int >::type = 0 >
21197 JSON_EXPLICIT operator ValueType() const
21198 {
21199 // delegate the call to get<>() const
21200 return get<ValueType>();
21201 }
21202
21206 {
21207 if (!is_binary())
21208 {
21209 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21210 }
21211
21212 return *get_ptr<binary_t*>();
21213 }
21214
21217 const binary_t& get_binary() const
21218 {
21219 if (!is_binary())
21220 {
21221 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21222 }
21223
21224 return *get_ptr<const binary_t*>();
21225 }
21226
21228
21230 // element access //
21232
21236
21240 {
21241 // at only works for arrays
21242 if (JSON_HEDLEY_LIKELY(is_array()))
21243 {
21244 JSON_TRY
21245 {
21246 return set_parent(m_data.m_value.array->at(idx));
21247 }
21248 JSON_CATCH(std::out_of_range&)
21249 {
21250 // create better exception explanation
21251 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21252 }
21253 }
21254 else
21255 {
21256 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21257 }
21258 }
21259
21263 {
21264 // at only works for arrays
21265 if (JSON_HEDLEY_LIKELY(is_array()))
21266 {
21267 JSON_TRY
21268 {
21269 return m_data.m_value.array->at(idx);
21270 }
21271 JSON_CATCH(std::out_of_range&)
21272 {
21273 // create better exception explanation
21274 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21275 }
21276 }
21277 else
21278 {
21279 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21280 }
21281 }
21282
21285 reference at(const typename object_t::key_type& key)
21286 {
21287 // at only works for objects
21288 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21289 {
21290 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21291 }
21292
21293 auto it = m_data.m_value.object->find(key);
21294 if (it == m_data.m_value.object->end())
21295 {
21296 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21297 }
21298 return set_parent(it->second);
21299 }
21300
21303 template<class KeyType, detail::enable_if_t<
21305 reference at(KeyType&& key)
21306 {
21307 // at only works for objects
21308 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21309 {
21310 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21311 }
21312
21313 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21314 if (it == m_data.m_value.object->end())
21315 {
21316 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21317 }
21318 return set_parent(it->second);
21319 }
21320
21323 const_reference at(const typename object_t::key_type& key) const
21324 {
21325 // at only works for objects
21326 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21327 {
21328 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21329 }
21330
21331 auto it = m_data.m_value.object->find(key);
21332 if (it == m_data.m_value.object->end())
21333 {
21334 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21335 }
21336 return it->second;
21337 }
21338
21341 template<class KeyType, detail::enable_if_t<
21343 const_reference at(KeyType&& key) const
21344 {
21345 // at only works for objects
21346 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21347 {
21348 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21349 }
21350
21351 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21352 if (it == m_data.m_value.object->end())
21353 {
21354 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21355 }
21356 return it->second;
21357 }
21358
21362 {
21363 // implicitly convert null value to an empty array
21364 if (is_null())
21365 {
21366 m_data.m_type = value_t::array;
21367 m_data.m_value.array = create<array_t>();
21368 assert_invariant();
21369 }
21370
21371 // operator[] only works for arrays
21372 if (JSON_HEDLEY_LIKELY(is_array()))
21373 {
21374 // fill up array with null values if given idx is outside range
21375 if (idx >= m_data.m_value.array->size())
21376 {
21377#if JSON_DIAGNOSTICS
21378 // remember array size & capacity before resizing
21379 const auto old_size = m_data.m_value.array->size();
21380 const auto old_capacity = m_data.m_value.array->capacity();
21381#endif
21382 m_data.m_value.array->resize(idx + 1);
21383
21384#if JSON_DIAGNOSTICS
21385 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21386 {
21387 // capacity has changed: update all parents
21388 set_parents();
21389 }
21390 else
21391 {
21392 // set parent for values added above
21393 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21394 }
21395#endif
21396 assert_invariant();
21397 }
21398
21399 return m_data.m_value.array->operator[](idx);
21400 }
21401
21402 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21403 }
21404
21408 {
21409 // const operator[] only works for arrays
21410 if (JSON_HEDLEY_LIKELY(is_array()))
21411 {
21412 return m_data.m_value.array->operator[](idx);
21413 }
21414
21415 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21416 }
21417
21420 reference operator[](typename object_t::key_type key)
21421 {
21422 // implicitly convert null value to an empty object
21423 if (is_null())
21424 {
21425 m_data.m_type = value_t::object;
21426 m_data.m_value.object = create<object_t>();
21427 assert_invariant();
21428 }
21429
21430 // operator[] only works for objects
21431 if (JSON_HEDLEY_LIKELY(is_object()))
21432 {
21433 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21434 return set_parent(result.first->second);
21435 }
21436
21437 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21438 }
21439
21442 const_reference operator[](const typename object_t::key_type& key) const
21443 {
21444 // const operator[] only works for objects
21445 if (JSON_HEDLEY_LIKELY(is_object()))
21446 {
21447 auto it = m_data.m_value.object->find(key);
21448 JSON_ASSERT(it != m_data.m_value.object->end());
21449 return it->second;
21450 }
21451
21452 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21453 }
21454
21455 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21456 // (they seemingly cannot be constrained to resolve the ambiguity)
21457 template<typename T>
21459 {
21460 return operator[](typename object_t::key_type(key));
21461 }
21462
21463 template<typename T>
21465 {
21466 return operator[](typename object_t::key_type(key));
21467 }
21468
21471 template<class KeyType, detail::enable_if_t<
21473 reference operator[](KeyType&& key)
21474 {
21475 // implicitly convert null value to an empty object
21476 if (is_null())
21477 {
21478 m_data.m_type = value_t::object;
21479 m_data.m_value.object = create<object_t>();
21480 assert_invariant();
21481 }
21482
21483 // operator[] only works for objects
21484 if (JSON_HEDLEY_LIKELY(is_object()))
21485 {
21486 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21487 return set_parent(result.first->second);
21488 }
21489
21490 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21491 }
21492
21495 template<class KeyType, detail::enable_if_t<
21497 const_reference operator[](KeyType&& key) const
21498 {
21499 // const operator[] only works for objects
21500 if (JSON_HEDLEY_LIKELY(is_object()))
21501 {
21502 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21503 JSON_ASSERT(it != m_data.m_value.object->end());
21504 return it->second;
21505 }
21506
21507 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21508 }
21509
21510private:
21511 template<typename KeyType>
21512 using is_comparable_with_object_key = detail::is_comparable <
21513 object_comparator_t, const typename object_t::key_type&, KeyType >;
21514
21515 template<typename ValueType>
21516 using value_return_type = std::conditional <
21518 string_t, typename std::decay<ValueType>::type >;
21519
21520public:
21523 template < class ValueType, detail::enable_if_t <
21526 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21527 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21528 {
21529 // value only works for objects
21530 if (JSON_HEDLEY_LIKELY(is_object()))
21531 {
21532 // if key is found, return value and given default value otherwise
21533 const auto it = find(key);
21534 if (it != end())
21535 {
21536 return it->template get<ValueType>();
21537 }
21538
21539 return default_value;
21540 }
21541
21542 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21543 }
21544
21547 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21551 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21552 ReturnType value(const typename object_t::key_type& key, ValueType&& default_value) const
21553 {
21554 // value only works for objects
21555 if (JSON_HEDLEY_LIKELY(is_object()))
21556 {
21557 // if key is found, return value and given default value otherwise
21558 const auto it = find(key);
21559 if (it != end())
21560 {
21561 return it->template get<ReturnType>();
21562 }
21563
21564 return std::forward<ValueType>(default_value);
21565 }
21566
21567 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21568 }
21569
21572 template < class ValueType, class KeyType, detail::enable_if_t <
21575 && is_comparable_with_object_key<KeyType>::value
21577 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21578 ValueType value(KeyType&& key, const ValueType& default_value) const
21579 {
21580 // value only works for objects
21581 if (JSON_HEDLEY_LIKELY(is_object()))
21582 {
21583 // if key is found, return value and given default value otherwise
21584 const auto it = find(std::forward<KeyType>(key));
21585 if (it != end())
21586 {
21587 return it->template get<ValueType>();
21588 }
21589
21590 return default_value;
21591 }
21592
21593 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21594 }
21595
21598 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21602 && is_comparable_with_object_key<KeyType>::value
21604 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21605 ReturnType value(KeyType&& key, ValueType&& default_value) const
21606 {
21607 // value only works for objects
21608 if (JSON_HEDLEY_LIKELY(is_object()))
21609 {
21610 // if key is found, return value and given default value otherwise
21611 const auto it = find(std::forward<KeyType>(key));
21612 if (it != end())
21613 {
21614 return it->template get<ReturnType>();
21615 }
21616
21617 return std::forward<ValueType>(default_value);
21618 }
21619
21620 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21621 }
21622
21625 template < class ValueType, detail::enable_if_t <
21627 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21628 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21629 {
21630 // value only works for objects
21631 if (JSON_HEDLEY_LIKELY(is_object()))
21632 {
21633 // if pointer resolves a value, return it or use default value
21634 JSON_TRY
21635 {
21636 return ptr.get_checked(this).template get<ValueType>();
21637 }
21639 {
21640 return default_value;
21641 }
21642 }
21643
21644 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21645 }
21646
21649 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21652 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21653 ReturnType value(const json_pointer& ptr, ValueType&& default_value) const
21654 {
21655 // value only works for objects
21656 if (JSON_HEDLEY_LIKELY(is_object()))
21657 {
21658 // if pointer resolves a value, return it or use default value
21659 JSON_TRY
21660 {
21661 return ptr.get_checked(this).template get<ReturnType>();
21662 }
21664 {
21665 return std::forward<ValueType>(default_value);
21666 }
21667 }
21668
21669 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21670 }
21671
21672 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21675 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21676 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21677 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21678 {
21679 return value(ptr.convert(), default_value);
21680 }
21681
21682 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21686 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21687 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21688 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType&& default_value) const
21689 {
21690 return value(ptr.convert(), std::forward<ValueType>(default_value));
21691 }
21692
21696 {
21697 return *begin();
21698 }
21699
21703 {
21704 return *cbegin();
21705 }
21706
21710 {
21711 auto tmp = end();
21712 --tmp;
21713 return *tmp;
21714 }
21715
21719 {
21720 auto tmp = cend();
21721 --tmp;
21722 return *tmp;
21723 }
21724
21727 template < class IteratorType, detail::enable_if_t <
21728 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21729 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21730 IteratorType erase(IteratorType pos)
21731 {
21732 // make sure iterator fits the current value
21733 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21734 {
21735 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21736 }
21737
21738 IteratorType result = end();
21739
21740 switch (m_data.m_type)
21741 {
21742 case value_t::boolean:
21743 case value_t::number_float:
21744 case value_t::number_integer:
21745 case value_t::number_unsigned:
21746 case value_t::string:
21747 case value_t::binary:
21748 {
21749 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21750 {
21751 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21752 }
21753
21754 if (is_string())
21755 {
21756 AllocatorType<string_t> alloc;
21757 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21758 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21759 m_data.m_value.string = nullptr;
21760 }
21761 else if (is_binary())
21762 {
21763 AllocatorType<binary_t> alloc;
21764 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21765 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21766 m_data.m_value.binary = nullptr;
21767 }
21768
21769 m_data.m_type = value_t::null;
21770 assert_invariant();
21771 break;
21772 }
21773
21774 case value_t::object:
21775 {
21776 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21777 break;
21778 }
21779
21780 case value_t::array:
21781 {
21782 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21783 break;
21784 }
21785
21786 case value_t::null:
21787 case value_t::discarded:
21788 default:
21789 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21790 }
21791
21792 return result;
21793 }
21794
21797 template < class IteratorType, detail::enable_if_t <
21798 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21799 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21800 IteratorType erase(IteratorType first, IteratorType last)
21801 {
21802 // make sure iterator fits the current value
21803 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21804 {
21805 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21806 }
21807
21808 IteratorType result = end();
21809
21810 switch (m_data.m_type)
21811 {
21812 case value_t::boolean:
21813 case value_t::number_float:
21814 case value_t::number_integer:
21815 case value_t::number_unsigned:
21816 case value_t::string:
21817 case value_t::binary:
21818 {
21819 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21820 || !last.m_it.primitive_iterator.is_end()))
21821 {
21822 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21823 }
21824
21825 if (is_string())
21826 {
21827 AllocatorType<string_t> alloc;
21828 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21829 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21830 m_data.m_value.string = nullptr;
21831 }
21832 else if (is_binary())
21833 {
21834 AllocatorType<binary_t> alloc;
21835 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21836 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21837 m_data.m_value.binary = nullptr;
21838 }
21839
21840 m_data.m_type = value_t::null;
21841 assert_invariant();
21842 break;
21843 }
21844
21845 case value_t::object:
21846 {
21847 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21848 last.m_it.object_iterator);
21849 break;
21850 }
21851
21852 case value_t::array:
21853 {
21854 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21855 last.m_it.array_iterator);
21856 break;
21857 }
21858
21859 case value_t::null:
21860 case value_t::discarded:
21861 default:
21862 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21863 }
21864
21865 return result;
21866 }
21867
21868private:
21869 template < typename KeyType, detail::enable_if_t <
21871 size_type erase_internal(KeyType&& key)
21872 {
21873 // this erase only works for objects
21874 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21875 {
21876 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21877 }
21878
21879 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21880 }
21881
21882 template < typename KeyType, detail::enable_if_t <
21884 size_type erase_internal(KeyType&& key)
21885 {
21886 // this erase only works for objects
21887 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21888 {
21889 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21890 }
21891
21892 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21893 if (it != m_data.m_value.object->end())
21894 {
21895 m_data.m_value.object->erase(it);
21896 return 1;
21897 }
21898 return 0;
21899 }
21900
21901public:
21902
21905 size_type erase(const typename object_t::key_type& key)
21906 {
21907 // the indirection via erase_internal() is added to avoid making this
21908 // function a template and thus de-rank it during overload resolution
21909 return erase_internal(key);
21910 }
21911
21914 template<class KeyType, detail::enable_if_t<
21916 size_type erase(KeyType&& key)
21917 {
21918 return erase_internal(std::forward<KeyType>(key));
21919 }
21920
21923 void erase(const size_type idx)
21924 {
21925 // this erase only works for arrays
21926 if (JSON_HEDLEY_LIKELY(is_array()))
21927 {
21928 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21929 {
21930 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21931 }
21932
21933 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21934 }
21935 else
21936 {
21937 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21938 }
21939 }
21940
21942
21944 // lookup //
21946
21949
21952 iterator find(const typename object_t::key_type& key)
21953 {
21954 auto result = end();
21955
21956 if (is_object())
21957 {
21958 result.m_it.object_iterator = m_data.m_value.object->find(key);
21959 }
21960
21961 return result;
21962 }
21963
21966 const_iterator find(const typename object_t::key_type& key) const
21967 {
21968 auto result = cend();
21969
21970 if (is_object())
21971 {
21972 result.m_it.object_iterator = m_data.m_value.object->find(key);
21973 }
21974
21975 return result;
21976 }
21977
21980 template<class KeyType, detail::enable_if_t<
21982 iterator find(KeyType&& key)
21983 {
21984 auto result = end();
21985
21986 if (is_object())
21987 {
21988 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
21989 }
21990
21991 return result;
21992 }
21993
21996 template<class KeyType, detail::enable_if_t<
21998 const_iterator find(KeyType&& key) const
21999 {
22000 auto result = cend();
22001
22002 if (is_object())
22003 {
22004 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22005 }
22006
22007 return result;
22008 }
22009
22012 size_type count(const typename object_t::key_type& key) const
22013 {
22014 // return 0 for all nonobject types
22015 return is_object() ? m_data.m_value.object->count(key) : 0;
22016 }
22017
22020 template<class KeyType, detail::enable_if_t<
22022 size_type count(KeyType&& key) const
22023 {
22024 // return 0 for all nonobject types
22025 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22026 }
22027
22030 bool contains(const typename object_t::key_type& key) const
22031 {
22032 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22033 }
22034
22037 template<class KeyType, detail::enable_if_t<
22039 bool contains(KeyType&& key) const
22040 {
22041 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22042 }
22043
22046 bool contains(const json_pointer& ptr) const
22047 {
22048 return ptr.contains(this);
22049 }
22050
22051 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22052 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22053 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22054 {
22055 return ptr.contains(this);
22056 }
22057
22059
22061 // iterators //
22063
22066
22069 iterator begin() noexcept
22070 {
22071 iterator result(this);
22072 result.set_begin();
22073 return result;
22074 }
22075
22078 const_iterator begin() const noexcept
22079 {
22080 return cbegin();
22081 }
22082
22085 const_iterator cbegin() const noexcept
22086 {
22087 const_iterator result(this);
22088 result.set_begin();
22089 return result;
22090 }
22091
22094 iterator end() noexcept
22095 {
22096 iterator result(this);
22097 result.set_end();
22098 return result;
22099 }
22100
22103 const_iterator end() const noexcept
22104 {
22105 return cend();
22106 }
22107
22110 const_iterator cend() const noexcept
22111 {
22112 const_iterator result(this);
22113 result.set_end();
22114 return result;
22115 }
22116
22120 {
22121 return reverse_iterator(end());
22122 }
22123
22127 {
22128 return crbegin();
22129 }
22130
22134 {
22135 return reverse_iterator(begin());
22136 }
22137
22141 {
22142 return crend();
22143 }
22144
22148 {
22149 return const_reverse_iterator(cend());
22150 }
22151
22155 {
22156 return const_reverse_iterator(cbegin());
22157 }
22158
22159public:
22165 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22166 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22167 {
22168 return ref.items();
22169 }
22170
22176 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22177 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22178 {
22179 return ref.items();
22180 }
22181
22184 iteration_proxy<iterator> items() noexcept
22185 {
22186 return iteration_proxy<iterator>(*this);
22187 }
22188
22191 iteration_proxy<const_iterator> items() const noexcept
22192 {
22193 return iteration_proxy<const_iterator>(*this);
22194 }
22195
22197
22199 // capacity //
22201
22204
22207 bool empty() const noexcept
22208 {
22209 switch (m_data.m_type)
22210 {
22211 case value_t::null:
22212 {
22213 // null values are empty
22214 return true;
22215 }
22216
22217 case value_t::array:
22218 {
22219 // delegate call to array_t::empty()
22220 return m_data.m_value.array->empty();
22221 }
22222
22223 case value_t::object:
22224 {
22225 // delegate call to object_t::empty()
22226 return m_data.m_value.object->empty();
22227 }
22228
22229 case value_t::string:
22230 case value_t::boolean:
22231 case value_t::number_integer:
22232 case value_t::number_unsigned:
22233 case value_t::number_float:
22234 case value_t::binary:
22235 case value_t::discarded:
22236 default:
22237 {
22238 // all other types are nonempty
22239 return false;
22240 }
22241 }
22242 }
22243
22246 size_type size() const noexcept
22247 {
22248 switch (m_data.m_type)
22249 {
22250 case value_t::null:
22251 {
22252 // null values are empty
22253 return 0;
22254 }
22255
22256 case value_t::array:
22257 {
22258 // delegate call to array_t::size()
22259 return m_data.m_value.array->size();
22260 }
22261
22262 case value_t::object:
22263 {
22264 // delegate call to object_t::size()
22265 return m_data.m_value.object->size();
22266 }
22267
22268 case value_t::string:
22269 case value_t::boolean:
22270 case value_t::number_integer:
22271 case value_t::number_unsigned:
22272 case value_t::number_float:
22273 case value_t::binary:
22274 case value_t::discarded:
22275 default:
22276 {
22277 // all other types have size 1
22278 return 1;
22279 }
22280 }
22281 }
22282
22285 size_type max_size() const noexcept
22286 {
22287 switch (m_data.m_type)
22288 {
22289 case value_t::array:
22290 {
22291 // delegate call to array_t::max_size()
22292 return m_data.m_value.array->max_size();
22293 }
22294
22295 case value_t::object:
22296 {
22297 // delegate call to object_t::max_size()
22298 return m_data.m_value.object->max_size();
22299 }
22300
22301 case value_t::null:
22302 case value_t::string:
22303 case value_t::boolean:
22304 case value_t::number_integer:
22305 case value_t::number_unsigned:
22306 case value_t::number_float:
22307 case value_t::binary:
22308 case value_t::discarded:
22309 default:
22310 {
22311 // all other types have max_size() == size()
22312 return size();
22313 }
22314 }
22315 }
22316
22318
22320 // modifiers //
22322
22325
22328 void clear() noexcept
22329 {
22330 switch (m_data.m_type)
22331 {
22332 case value_t::number_integer:
22333 {
22334 m_data.m_value.number_integer = 0;
22335 break;
22336 }
22337
22338 case value_t::number_unsigned:
22339 {
22340 m_data.m_value.number_unsigned = 0;
22341 break;
22342 }
22343
22344 case value_t::number_float:
22345 {
22346 m_data.m_value.number_float = 0.0;
22347 break;
22348 }
22349
22350 case value_t::boolean:
22351 {
22352 m_data.m_value.boolean = false;
22353 break;
22354 }
22355
22356 case value_t::string:
22357 {
22358 m_data.m_value.string->clear();
22359 break;
22360 }
22361
22362 case value_t::binary:
22363 {
22364 m_data.m_value.binary->clear();
22365 break;
22366 }
22367
22368 case value_t::array:
22369 {
22370 m_data.m_value.array->clear();
22371 break;
22372 }
22373
22374 case value_t::object:
22375 {
22376 m_data.m_value.object->clear();
22377 break;
22378 }
22379
22380 case value_t::null:
22381 case value_t::discarded:
22382 default:
22383 break;
22384 }
22385 }
22386
22390 {
22391 // push_back only works for null objects or arrays
22392 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22393 {
22394 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22395 }
22396
22397 // transform null object into an array
22398 if (is_null())
22399 {
22400 m_data.m_type = value_t::array;
22401 m_data.m_value = value_t::array;
22402 assert_invariant();
22403 }
22404
22405 // add element to array (move semantics)
22406 const auto old_capacity = m_data.m_value.array->capacity();
22407 m_data.m_value.array->push_back(std::move(val));
22408 set_parent(m_data.m_value.array->back(), old_capacity);
22409 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22410 }
22411
22415 {
22416 push_back(std::move(val));
22417 return *this;
22418 }
22419
22422 void push_back(const basic_json& val)
22423 {
22424 // push_back only works for null objects or arrays
22425 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22426 {
22427 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22428 }
22429
22430 // transform null object into an array
22431 if (is_null())
22432 {
22433 m_data.m_type = value_t::array;
22434 m_data.m_value = value_t::array;
22435 assert_invariant();
22436 }
22437
22438 // add element to array
22439 const auto old_capacity = m_data.m_value.array->capacity();
22440 m_data.m_value.array->push_back(val);
22441 set_parent(m_data.m_value.array->back(), old_capacity);
22442 }
22443
22447 {
22448 push_back(val);
22449 return *this;
22450 }
22451
22454 void push_back(const typename object_t::value_type& val)
22455 {
22456 // push_back only works for null objects or objects
22457 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22458 {
22459 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22460 }
22461
22462 // transform null object into an object
22463 if (is_null())
22464 {
22465 m_data.m_type = value_t::object;
22466 m_data.m_value = value_t::object;
22467 assert_invariant();
22468 }
22469
22470 // add element to object
22471 auto res = m_data.m_value.object->insert(val);
22472 set_parent(res.first->second);
22473 }
22474
22477 reference operator+=(const typename object_t::value_type& val)
22478 {
22479 push_back(val);
22480 return *this;
22481 }
22482
22486 {
22487 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22488 {
22489 basic_json&& key = init.begin()->moved_or_copied();
22490 push_back(typename object_t::value_type(
22491 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22492 }
22493 else
22494 {
22495 push_back(basic_json(init));
22496 }
22497 }
22498
22502 {
22503 push_back(init);
22504 return *this;
22505 }
22506
22509 template<class... Args>
22510 reference emplace_back(Args&& ... args)
22511 {
22512 // emplace_back only works for null objects or arrays
22513 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22514 {
22515 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22516 }
22517
22518 // transform null object into an array
22519 if (is_null())
22520 {
22521 m_data.m_type = value_t::array;
22522 m_data.m_value = value_t::array;
22523 assert_invariant();
22524 }
22525
22526 // add element to array (perfect forwarding)
22527 const auto old_capacity = m_data.m_value.array->capacity();
22528 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22529 return set_parent(m_data.m_value.array->back(), old_capacity);
22530 }
22531
22534 template<class... Args>
22535 std::pair<iterator, bool> emplace(Args&& ... args)
22536 {
22537 // emplace only works for null objects or arrays
22538 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22539 {
22540 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22541 }
22542
22543 // transform null object into an object
22544 if (is_null())
22545 {
22546 m_data.m_type = value_t::object;
22547 m_data.m_value = value_t::object;
22548 assert_invariant();
22549 }
22550
22551 // add element to array (perfect forwarding)
22552 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22553 set_parent(res.first->second);
22554
22555 // create result iterator and set iterator to the result of emplace
22556 auto it = begin();
22557 it.m_it.object_iterator = res.first;
22558
22559 // return pair of iterator and boolean
22560 return { it, res.second };
22561 }
22562
22566 template<typename... Args>
22568 {
22569 iterator result(this);
22570 JSON_ASSERT(m_data.m_value.array != nullptr);
22571
22572 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22573 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22574 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22575
22576 // This could have been written as:
22577 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22578 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22579
22580 set_parents();
22581 return result;
22582 }
22583
22587 {
22588 // insert only works for arrays
22589 if (JSON_HEDLEY_LIKELY(is_array()))
22590 {
22591 // check if iterator pos fits to this JSON value
22592 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22593 {
22594 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22595 }
22596
22597 // insert to array and return iterator
22598 return insert_iterator(pos, val);
22599 }
22600
22601 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22602 }
22603
22607 {
22608 return insert(pos, val);
22609 }
22610
22614 {
22615 // insert only works for arrays
22616 if (JSON_HEDLEY_LIKELY(is_array()))
22617 {
22618 // check if iterator pos fits to this JSON value
22619 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22620 {
22621 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22622 }
22623
22624 // insert to array and return iterator
22625 return insert_iterator(pos, cnt, val);
22626 }
22627
22628 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22629 }
22630
22634 {
22635 // insert only works for arrays
22636 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22637 {
22638 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22639 }
22640
22641 // check if iterator pos fits to this JSON value
22642 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22643 {
22644 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22645 }
22646
22647 // check if range iterators belong to the same JSON object
22648 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22649 {
22650 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22651 }
22652
22653 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22654 {
22655 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22656 }
22657
22658 // insert to array and return iterator
22659 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22660 }
22661
22665 {
22666 // insert only works for arrays
22667 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22668 {
22669 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22670 }
22671
22672 // check if iterator pos fits to this JSON value
22673 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22674 {
22675 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22676 }
22677
22678 // insert to array and return iterator
22679 return insert_iterator(pos, ilist.begin(), ilist.end());
22680 }
22681
22685 {
22686 // insert only works for objects
22687 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22688 {
22689 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22690 }
22691
22692 // check if range iterators belong to the same JSON object
22693 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22694 {
22695 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22696 }
22697
22698 // passed iterators must belong to objects
22699 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22700 {
22701 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22702 }
22703
22704 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22705 }
22706
22709 void update(const_reference j, bool merge_objects = false)
22710 {
22711 update(j.begin(), j.end(), merge_objects);
22712 }
22713
22716 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22717 {
22718 // implicitly convert null value to an empty object
22719 if (is_null())
22720 {
22721 m_data.m_type = value_t::object;
22722 m_data.m_value.object = create<object_t>();
22723 assert_invariant();
22724 }
22725
22726 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22727 {
22728 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22729 }
22730
22731 // check if range iterators belong to the same JSON object
22732 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22733 {
22734 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22735 }
22736
22737 // passed iterators must belong to objects
22738 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22739 {
22740 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22741 }
22742
22743 for (auto it = first; it != last; ++it)
22744 {
22745 if (merge_objects && it.value().is_object())
22746 {
22747 auto it2 = m_data.m_value.object->find(it.key());
22748 if (it2 != m_data.m_value.object->end())
22749 {
22750 it2->second.update(it.value(), true);
22751 continue;
22752 }
22753 }
22754 m_data.m_value.object->operator[](it.key()) = it.value();
22755#if JSON_DIAGNOSTICS
22756 m_data.m_value.object->operator[](it.key()).m_parent = this;
22757#endif
22758 }
22759 }
22760
22763 void swap(reference other) noexcept (
22764 std::is_nothrow_move_constructible<value_t>::value&&
22765 std::is_nothrow_move_assignable<value_t>::value&&
22766 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22767 std::is_nothrow_move_assignable<json_value>::value
22768 )
22769 {
22770 std::swap(m_data.m_type, other.m_data.m_type);
22771 std::swap(m_data.m_value, other.m_data.m_value);
22772
22773 set_parents();
22774 other.set_parents();
22775 assert_invariant();
22776 }
22777
22780 friend void swap(reference left, reference right) noexcept (
22781 std::is_nothrow_move_constructible<value_t>::value&&
22782 std::is_nothrow_move_assignable<value_t>::value&&
22783 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22784 std::is_nothrow_move_assignable<json_value>::value
22785 )
22786 {
22787 left.swap(right);
22788 }
22789
22792 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22793 {
22794 // swap only works for arrays
22795 if (JSON_HEDLEY_LIKELY(is_array()))
22796 {
22797 using std::swap;
22798 swap(*(m_data.m_value.array), other);
22799 }
22800 else
22801 {
22802 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22803 }
22804 }
22805
22808 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22809 {
22810 // swap only works for objects
22811 if (JSON_HEDLEY_LIKELY(is_object()))
22812 {
22813 using std::swap;
22814 swap(*(m_data.m_value.object), other);
22815 }
22816 else
22817 {
22818 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22819 }
22820 }
22821
22824 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22825 {
22826 // swap only works for strings
22827 if (JSON_HEDLEY_LIKELY(is_string()))
22828 {
22829 using std::swap;
22830 swap(*(m_data.m_value.string), other);
22831 }
22832 else
22833 {
22834 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22835 }
22836 }
22837
22840 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22841 {
22842 // swap only works for strings
22843 if (JSON_HEDLEY_LIKELY(is_binary()))
22844 {
22845 using std::swap;
22846 swap(*(m_data.m_value.binary), other);
22847 }
22848 else
22849 {
22850 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22851 }
22852 }
22853
22856 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22857 {
22858 // swap only works for strings
22859 if (JSON_HEDLEY_LIKELY(is_binary()))
22860 {
22861 using std::swap;
22862 swap(*(m_data.m_value.binary), other);
22863 }
22864 else
22865 {
22866 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22867 }
22868 }
22869
22871
22873 // lexicographical comparison operators //
22875
22878
22879 // note parentheses around operands are necessary; see
22880 // https://github.com/nlohmann/json/issues/1530
22881#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22882 const auto lhs_type = lhs.type(); \
22883 const auto rhs_type = rhs.type(); \
22884 \
22885 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22886 { \
22887 switch (lhs_type) \
22888 { \
22889 case value_t::array: \
22890 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22891 \
22892 case value_t::object: \
22893 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22894 \
22895 case value_t::null: \
22896 return (null_result); \
22897 \
22898 case value_t::string: \
22899 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22900 \
22901 case value_t::boolean: \
22902 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22903 \
22904 case value_t::number_integer: \
22905 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22906 \
22907 case value_t::number_unsigned: \
22908 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22909 \
22910 case value_t::number_float: \
22911 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22912 \
22913 case value_t::binary: \
22914 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22915 \
22916 case value_t::discarded: \
22917 default: \
22918 return (unordered_result); \
22919 } \
22920 } \
22921 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22922 { \
22923 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22924 } \
22925 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22926 { \
22927 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22928 } \
22929 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22930 { \
22931 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22932 } \
22933 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22934 { \
22935 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22936 } \
22937 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22938 { \
22939 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22940 } \
22941 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22942 { \
22943 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22944 } \
22945 else if(compares_unordered(lhs, rhs))\
22946 {\
22947 return (unordered_result);\
22948 }\
22949 \
22950 return (default_result);
22951
22953 // returns true if:
22954 // - any operand is NaN and the other operand is of number type
22955 // - any operand is discarded
22956 // in legacy mode, discarded values are considered ordered if
22957 // an operation is computed as an odd number of inverses of others
22958 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22959 {
22960 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22961 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22962 {
22963 return true;
22964 }
22965#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22966 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22967#else
22968 static_cast<void>(inverse);
22969 return lhs.is_discarded() || rhs.is_discarded();
22970#endif
22971 }
22972
22973private:
22974 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22975 {
22976 return compares_unordered(*this, rhs, inverse);
22977 }
22978
22979public:
22980#if JSON_HAS_THREE_WAY_COMPARISON
22983 bool operator==(const_reference rhs) const noexcept
22984 {
22985#ifdef __GNUC__
22986#pragma GCC diagnostic push
22987#pragma GCC diagnostic ignored "-Wfloat-equal"
22988#endif
22989 const_reference lhs = *this;
22990 JSON_IMPLEMENT_OPERATOR(== , true, false, false)
22991#ifdef __GNUC__
22992#pragma GCC diagnostic pop
22993#endif
22994 }
22995
22998 template<typename ScalarType>
22999 requires std::is_scalar_v<ScalarType>
23000 bool operator==(ScalarType rhs) const noexcept
23001 {
23002 return *this == basic_json(rhs);
23003 }
23004
23007 bool operator!=(const_reference rhs) const noexcept
23008 {
23009 if (compares_unordered(rhs, true))
23010 {
23011 return false;
23012 }
23013 return !operator==(rhs);
23014 }
23015
23018 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23019 {
23020 const_reference lhs = *this;
23021 // default_result is used if we cannot compare values. In that case,
23022 // we compare types.
23023 JSON_IMPLEMENT_OPERATOR(<=> , // *NOPAD*
23024 std::partial_ordering::equivalent,
23025 std::partial_ordering::unordered,
23026 lhs_type <=> rhs_type) // *NOPAD*
23027 }
23028
23031 template<typename ScalarType>
23032 requires std::is_scalar_v<ScalarType>
23033 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23034 {
23035 return *this <=> basic_json(rhs); // *NOPAD*
23036 }
23037
23038#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23039 // all operators that are computed as an odd number of inverses of others
23040 // need to be overloaded to emulate the legacy comparison behavior
23041
23045 bool operator<=(const_reference rhs) const noexcept
23046 {
23047 if (compares_unordered(rhs, true))
23048 {
23049 return false;
23050 }
23051 return !(rhs < *this);
23052 }
23053
23056 template<typename ScalarType>
23057 requires std::is_scalar_v<ScalarType>
23058 bool operator<=(ScalarType rhs) const noexcept
23059 {
23060 return *this <= basic_json(rhs);
23061 }
23062
23066 bool operator>=(const_reference rhs) const noexcept
23067 {
23068 if (compares_unordered(rhs, true))
23069 {
23070 return false;
23071 }
23072 return !(*this < rhs);
23073 }
23074
23077 template<typename ScalarType>
23078 requires std::is_scalar_v<ScalarType>
23079 bool operator>=(ScalarType rhs) const noexcept
23080 {
23081 return *this >= basic_json(rhs);
23082 }
23083#endif
23084#else
23087 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23088 {
23089#ifdef __GNUC__
23090#pragma GCC diagnostic push
23091#pragma GCC diagnostic ignored "-Wfloat-equal"
23092#endif
23093 JSON_IMPLEMENT_OPERATOR(== , true, false, false)
23094#ifdef __GNUC__
23095#pragma GCC diagnostic pop
23096#endif
23097 }
23098
23101 template<typename ScalarType, typename std::enable_if<
23102 std::is_scalar<ScalarType>::value, int>::type = 0>
23103 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23104 {
23105 return lhs == basic_json(rhs);
23106 }
23107
23110 template<typename ScalarType, typename std::enable_if<
23111 std::is_scalar<ScalarType>::value, int>::type = 0>
23112 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23113 {
23114 return basic_json(lhs) == rhs;
23115 }
23116
23119 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23120 {
23121 if (compares_unordered(lhs, rhs, true))
23122 {
23123 return false;
23124 }
23125 return !(lhs == rhs);
23126 }
23127
23130 template<typename ScalarType, typename std::enable_if<
23131 std::is_scalar<ScalarType>::value, int>::type = 0>
23132 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23133 {
23134 return lhs != basic_json(rhs);
23135 }
23136
23139 template<typename ScalarType, typename std::enable_if<
23140 std::is_scalar<ScalarType>::value, int>::type = 0>
23141 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23142 {
23143 return basic_json(lhs) != rhs;
23144 }
23145
23148 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23149 {
23150 // default_result is used if we cannot compare values. In that case,
23151 // we compare types. Note we have to call the operator explicitly,
23152 // because MSVC has problems otherwise.
23153 JSON_IMPLEMENT_OPERATOR(< , false, false, operator<(lhs_type, rhs_type))
23154 }
23155
23158 template<typename ScalarType, typename std::enable_if<
23159 std::is_scalar<ScalarType>::value, int>::type = 0>
23160 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23161 {
23162 return lhs < basic_json(rhs);
23163 }
23164
23167 template<typename ScalarType, typename std::enable_if<
23168 std::is_scalar<ScalarType>::value, int>::type = 0>
23169 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23170 {
23171 return basic_json(lhs) < rhs;
23172 }
23173
23176 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23177 {
23178 if (compares_unordered(lhs, rhs, true))
23179 {
23180 return false;
23181 }
23182 return !(rhs < lhs);
23183 }
23184
23187 template<typename ScalarType, typename std::enable_if<
23188 std::is_scalar<ScalarType>::value, int>::type = 0>
23189 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23190 {
23191 return lhs <= basic_json(rhs);
23192 }
23193
23196 template<typename ScalarType, typename std::enable_if<
23197 std::is_scalar<ScalarType>::value, int>::type = 0>
23198 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23199 {
23200 return basic_json(lhs) <= rhs;
23201 }
23202
23205 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23206 {
23207 // double inverse
23208 if (compares_unordered(lhs, rhs))
23209 {
23210 return false;
23211 }
23212 return !(lhs <= rhs);
23213 }
23214
23217 template<typename ScalarType, typename std::enable_if<
23218 std::is_scalar<ScalarType>::value, int>::type = 0>
23219 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23220 {
23221 return lhs > basic_json(rhs);
23222 }
23223
23226 template<typename ScalarType, typename std::enable_if<
23227 std::is_scalar<ScalarType>::value, int>::type = 0>
23228 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23229 {
23230 return basic_json(lhs) > rhs;
23231 }
23232
23235 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23236 {
23237 if (compares_unordered(lhs, rhs, true))
23238 {
23239 return false;
23240 }
23241 return !(lhs < rhs);
23242 }
23243
23246 template<typename ScalarType, typename std::enable_if<
23247 std::is_scalar<ScalarType>::value, int>::type = 0>
23248 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23249 {
23250 return lhs >= basic_json(rhs);
23251 }
23252
23255 template<typename ScalarType, typename std::enable_if<
23256 std::is_scalar<ScalarType>::value, int>::type = 0>
23257 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23258 {
23259 return basic_json(lhs) >= rhs;
23260 }
23261#endif
23262
23263#undef JSON_IMPLEMENT_OPERATOR
23264
23266
23268 // serialization //
23270
23273#ifndef JSON_NO_IO
23276 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23277 {
23278 // read width member and use it as indentation parameter if nonzero
23279 const bool pretty_print = o.width() > 0;
23280 const auto indentation = pretty_print ? o.width() : 0;
23281
23282 // reset width to 0 for subsequent calls to this stream
23283 o.width(0);
23284
23285 // do the actual serialization
23286 serializer s(detail::output_adapter<char>(o), o.fill());
23287 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23288 return o;
23289 }
23290
23297 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23298 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23299 {
23300 return o << j;
23301 }
23302#endif // JSON_NO_IO
23304
23306 // deserialization //
23308
23311
23314 template<typename InputType>
23316 static basic_json parse(InputType&& i,
23317 const parser_callback_t cb = nullptr,
23318 const bool allow_exceptions = true,
23319 const bool ignore_comments = false)
23320 {
23321 basic_json result;
23322 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23323 return result;
23324 }
23325
23328 template<typename IteratorType>
23330 static basic_json parse(IteratorType first,
23331 IteratorType last,
23332 const parser_callback_t cb = nullptr,
23333 const bool allow_exceptions = true,
23334 const bool ignore_comments = false)
23335 {
23336 basic_json result;
23337 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23338 return result;
23339 }
23340
23342 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23343 static basic_json parse(detail::span_input_adapter&& i,
23344 const parser_callback_t cb = nullptr,
23345 const bool allow_exceptions = true,
23346 const bool ignore_comments = false)
23347 {
23348 basic_json result;
23349 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23350 return result;
23351 }
23352
23355 template<typename InputType>
23356 static bool accept(InputType&& i,
23357 const bool ignore_comments = false)
23358 {
23359 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23360 }
23361
23364 template<typename IteratorType>
23365 static bool accept(IteratorType first, IteratorType last,
23366 const bool ignore_comments = false)
23367 {
23368 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23369 }
23370
23372 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23373 static bool accept(detail::span_input_adapter&& i,
23374 const bool ignore_comments = false)
23375 {
23376 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23377 }
23378
23381 template <typename InputType, typename SAX>
23383 static bool sax_parse(InputType&& i, SAX* sax,
23385 const bool strict = true,
23386 const bool ignore_comments = false)
23387 {
23388 auto ia = detail::input_adapter(std::forward<InputType>(i));
23389 return format == input_format_t::json
23390 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23391 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23392 }
23393
23396 template<class IteratorType, class SAX>
23398 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23400 const bool strict = true,
23401 const bool ignore_comments = false)
23402 {
23403 auto ia = detail::input_adapter(std::move(first), std::move(last));
23404 return format == input_format_t::json
23405 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23406 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23407 }
23408
23414 template <typename SAX>
23415 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23417 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23419 const bool strict = true,
23420 const bool ignore_comments = false)
23421 {
23422 auto ia = i.get();
23423 return format == input_format_t::json
23424 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23425 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23426 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23427 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23428 }
23429#ifndef JSON_NO_IO
23436 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23437 friend std::istream& operator<<(basic_json& j, std::istream& i)
23438 {
23439 return operator>>(i, j);
23440 }
23441
23444 friend std::istream& operator>>(std::istream& i, basic_json& j)
23445 {
23446 parser(detail::input_adapter(i)).parse(false, j);
23447 return i;
23448 }
23449#endif // JSON_NO_IO
23451
23453 // convenience functions //
23455
23459 const char* type_name() const noexcept
23460 {
23461 switch (m_data.m_type)
23462 {
23463 case value_t::null:
23464 return "null";
23465 case value_t::object:
23466 return "object";
23467 case value_t::array:
23468 return "array";
23469 case value_t::string:
23470 return "string";
23471 case value_t::boolean:
23472 return "boolean";
23473 case value_t::binary:
23474 return "binary";
23475 case value_t::discarded:
23476 return "discarded";
23477 case value_t::number_integer:
23478 case value_t::number_unsigned:
23479 case value_t::number_float:
23480 default:
23481 return "number";
23482 }
23483 }
23484
23487 // member variables //
23489
23490 struct data
23491 {
23493 value_t m_type = value_t::null;
23494
23496 json_value m_value = {};
23497
23498 data(const value_t v)
23499 : m_type(v), m_value(v)
23500 {
23501 }
23502
23503 data(size_type cnt, const basic_json& val)
23504 : m_type(value_t::array)
23505 {
23506 m_value.array = create<array_t>(cnt, val);
23507 }
23508
23509 data() noexcept = default;
23510 data(data&&) noexcept = default;
23511 data(const data&) noexcept = delete;
23512 data& operator=(data&&) noexcept = delete;
23513 data& operator=(const data&) noexcept = delete;
23514
23515 ~data() noexcept
23516 {
23517 m_value.destroy(m_type);
23518 }
23519 };
23520
23521 data m_data = {};
23522
23523#if JSON_DIAGNOSTICS
23525 basic_json* m_parent = nullptr;
23526#endif
23527
23529 // binary serialization/deserialization //
23531
23534
23535public:
23538 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23539 {
23540 std::vector<std::uint8_t> result;
23541 to_cbor(j, result);
23542 return result;
23543 }
23544
23548 {
23549 binary_writer<std::uint8_t>(o).write_cbor(j);
23550 }
23551
23555 {
23556 binary_writer<char>(o).write_cbor(j);
23557 }
23558
23561 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23562 {
23563 std::vector<std::uint8_t> result;
23564 to_msgpack(j, result);
23565 return result;
23566 }
23567
23571 {
23572 binary_writer<std::uint8_t>(o).write_msgpack(j);
23573 }
23574
23578 {
23579 binary_writer<char>(o).write_msgpack(j);
23580 }
23581
23584 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23585 const bool use_size = false,
23586 const bool use_type = false)
23587 {
23588 std::vector<std::uint8_t> result;
23589 to_ubjson(j, result, use_size, use_type);
23590 return result;
23591 }
23592
23596 const bool use_size = false, const bool use_type = false)
23597 {
23598 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23599 }
23600
23604 const bool use_size = false, const bool use_type = false)
23605 {
23606 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23607 }
23608
23611 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23612 const bool use_size = false,
23613 const bool use_type = false)
23614 {
23615 std::vector<std::uint8_t> result;
23616 to_bjdata(j, result, use_size, use_type);
23617 return result;
23618 }
23619
23623 const bool use_size = false, const bool use_type = false)
23624 {
23625 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23626 }
23627
23631 const bool use_size = false, const bool use_type = false)
23632 {
23633 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23634 }
23635
23638 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23639 {
23640 std::vector<std::uint8_t> result;
23641 to_bson(j, result);
23642 return result;
23643 }
23644
23648 {
23649 binary_writer<std::uint8_t>(o).write_bson(j);
23650 }
23651
23655 {
23656 binary_writer<char>(o).write_bson(j);
23657 }
23658
23661 template<typename InputType>
23663 static basic_json from_cbor(InputType&& i,
23664 const bool strict = true,
23665 const bool allow_exceptions = true,
23666 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23667 {
23668 basic_json result;
23669 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23670 auto ia = detail::input_adapter(std::forward<InputType>(i));
23671 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23672 return res ? result : basic_json(value_t::discarded);
23673 }
23674
23677 template<typename IteratorType>
23679 static basic_json from_cbor(IteratorType first, IteratorType last,
23680 const bool strict = true,
23681 const bool allow_exceptions = true,
23682 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23683 {
23684 basic_json result;
23685 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23686 auto ia = detail::input_adapter(std::move(first), std::move(last));
23687 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23688 return res ? result : basic_json(value_t::discarded);
23689 }
23690
23691 template<typename T>
23693 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23694 static basic_json from_cbor(const T* ptr, std::size_t len,
23695 const bool strict = true,
23696 const bool allow_exceptions = true,
23697 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23698 {
23699 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23700 }
23701
23703 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23704 static basic_json from_cbor(detail::span_input_adapter&& i,
23705 const bool strict = true,
23706 const bool allow_exceptions = true,
23707 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23708 {
23709 basic_json result;
23710 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23711 auto ia = i.get();
23712 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23713 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23714 return res ? result : basic_json(value_t::discarded);
23715 }
23716
23719 template<typename InputType>
23721 static basic_json from_msgpack(InputType&& i,
23722 const bool strict = true,
23723 const bool allow_exceptions = true)
23724 {
23725 basic_json result;
23726 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23727 auto ia = detail::input_adapter(std::forward<InputType>(i));
23728 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23729 return res ? result : basic_json(value_t::discarded);
23730 }
23731
23734 template<typename IteratorType>
23736 static basic_json from_msgpack(IteratorType first, IteratorType last,
23737 const bool strict = true,
23738 const bool allow_exceptions = true)
23739 {
23740 basic_json result;
23741 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23742 auto ia = detail::input_adapter(std::move(first), std::move(last));
23743 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23744 return res ? result : basic_json(value_t::discarded);
23745 }
23746
23747 template<typename T>
23749 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23750 static basic_json from_msgpack(const T* ptr, std::size_t len,
23751 const bool strict = true,
23752 const bool allow_exceptions = true)
23753 {
23754 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23755 }
23756
23758 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23759 static basic_json from_msgpack(detail::span_input_adapter&& i,
23760 const bool strict = true,
23761 const bool allow_exceptions = true)
23762 {
23763 basic_json result;
23764 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23765 auto ia = i.get();
23766 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23767 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23768 return res ? result : basic_json(value_t::discarded);
23769 }
23770
23773 template<typename InputType>
23775 static basic_json from_ubjson(InputType&& i,
23776 const bool strict = true,
23777 const bool allow_exceptions = true)
23778 {
23779 basic_json result;
23780 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23781 auto ia = detail::input_adapter(std::forward<InputType>(i));
23782 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23783 return res ? result : basic_json(value_t::discarded);
23784 }
23785
23788 template<typename IteratorType>
23790 static basic_json from_ubjson(IteratorType first, IteratorType last,
23791 const bool strict = true,
23792 const bool allow_exceptions = true)
23793 {
23794 basic_json result;
23795 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23796 auto ia = detail::input_adapter(std::move(first), std::move(last));
23797 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23798 return res ? result : basic_json(value_t::discarded);
23799 }
23800
23801 template<typename T>
23803 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23804 static basic_json from_ubjson(const T* ptr, std::size_t len,
23805 const bool strict = true,
23806 const bool allow_exceptions = true)
23807 {
23808 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23809 }
23810
23812 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23813 static basic_json from_ubjson(detail::span_input_adapter&& i,
23814 const bool strict = true,
23815 const bool allow_exceptions = true)
23816 {
23817 basic_json result;
23818 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23819 auto ia = i.get();
23820 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23821 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23822 return res ? result : basic_json(value_t::discarded);
23823 }
23824
23827 template<typename InputType>
23829 static basic_json from_bjdata(InputType&& i,
23830 const bool strict = true,
23831 const bool allow_exceptions = true)
23832 {
23833 basic_json result;
23834 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23835 auto ia = detail::input_adapter(std::forward<InputType>(i));
23836 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23837 return res ? result : basic_json(value_t::discarded);
23838 }
23839
23842 template<typename IteratorType>
23844 static basic_json from_bjdata(IteratorType first, IteratorType last,
23845 const bool strict = true,
23846 const bool allow_exceptions = true)
23847 {
23848 basic_json result;
23849 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23850 auto ia = detail::input_adapter(std::move(first), std::move(last));
23851 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23852 return res ? result : basic_json(value_t::discarded);
23853 }
23854
23857 template<typename InputType>
23859 static basic_json from_bson(InputType&& i,
23860 const bool strict = true,
23861 const bool allow_exceptions = true)
23862 {
23863 basic_json result;
23864 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23865 auto ia = detail::input_adapter(std::forward<InputType>(i));
23866 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23867 return res ? result : basic_json(value_t::discarded);
23868 }
23869
23872 template<typename IteratorType>
23874 static basic_json from_bson(IteratorType first, IteratorType last,
23875 const bool strict = true,
23876 const bool allow_exceptions = true)
23877 {
23878 basic_json result;
23879 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23880 auto ia = detail::input_adapter(std::move(first), std::move(last));
23881 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23882 return res ? result : basic_json(value_t::discarded);
23883 }
23884
23885 template<typename T>
23887 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23888 static basic_json from_bson(const T* ptr, std::size_t len,
23889 const bool strict = true,
23890 const bool allow_exceptions = true)
23891 {
23892 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23893 }
23894
23896 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23897 static basic_json from_bson(detail::span_input_adapter&& i,
23898 const bool strict = true,
23899 const bool allow_exceptions = true)
23900 {
23901 basic_json result;
23902 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23903 auto ia = i.get();
23904 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23905 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23906 return res ? result : basic_json(value_t::discarded);
23907 }
23909
23911 // JSON Pointer support //
23913
23916
23920 {
23921 return ptr.get_unchecked(this);
23922 }
23923
23924 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23925 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23926 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23927 {
23928 return ptr.get_unchecked(this);
23929 }
23930
23934 {
23935 return ptr.get_unchecked(this);
23936 }
23937
23938 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23939 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23940 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23941 {
23942 return ptr.get_unchecked(this);
23943 }
23944
23948 {
23949 return ptr.get_checked(this);
23950 }
23951
23952 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23953 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23954 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23955 {
23956 return ptr.get_checked(this);
23957 }
23958
23962 {
23963 return ptr.get_checked(this);
23964 }
23965
23966 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23967 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23968 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23969 {
23970 return ptr.get_checked(this);
23971 }
23972
23976 {
23977 basic_json result(value_t::object);
23978 json_pointer::flatten("", *this, result);
23979 return result;
23980 }
23981
23985 {
23986 return json_pointer::unflatten(*this);
23987 }
23988
23990
23992 // JSON Patch functions //
23994
23997
24000 void patch_inplace(const basic_json& json_patch)
24001 {
24002 basic_json& result = *this;
24003 // the valid JSON Patch operations
24004 enum class patch_operations { add, remove, replace, move, copy, test, invalid };
24005
24006 const auto get_op = [](const std::string& op)
24007 {
24008 if (op == "add")
24009 {
24010 return patch_operations::add;
24011 }
24012 if (op == "remove")
24013 {
24014 return patch_operations::remove;
24015 }
24016 if (op == "replace")
24017 {
24018 return patch_operations::replace;
24019 }
24020 if (op == "move")
24021 {
24022 return patch_operations::move;
24023 }
24024 if (op == "copy")
24025 {
24026 return patch_operations::copy;
24027 }
24028 if (op == "test")
24029 {
24030 return patch_operations::test;
24031 }
24032
24033 return patch_operations::invalid;
24034 };
24035
24036 // wrapper for "add" operation; add value at ptr
24037 const auto operation_add = [&result](json_pointer& ptr, basic_json val)
24038 {
24039 // adding to the root of the target document means replacing it
24040 if (ptr.empty())
24041 {
24042 result = val;
24043 return;
24044 }
24045
24046 // make sure the top element of the pointer exists
24047 json_pointer const top_pointer = ptr.top();
24048 if (top_pointer != ptr)
24049 {
24050 result.at(top_pointer);
24051 }
24052
24053 // get reference to parent of JSON pointer ptr
24054 const auto last_path = ptr.back();
24055 ptr.pop_back();
24056 // parent must exist when performing patch add per RFC6902 specs
24057 basic_json& parent = result.at(ptr);
24058
24059 switch (parent.m_data.m_type)
24060 {
24061 case value_t::null:
24062 case value_t::object:
24063 {
24064 // use operator[] to add value
24065 parent[last_path] = val;
24066 break;
24067 }
24068
24069 case value_t::array:
24070 {
24071 if (last_path == "-")
24072 {
24073 // special case: append to back
24074 parent.push_back(val);
24075 }
24076 else
24077 {
24078 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24079 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24080 {
24081 // avoid undefined behavior
24082 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24083 }
24084
24085 // default case: insert add offset
24086 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24087 }
24088 break;
24089 }
24090
24091 // if there exists a parent it cannot be primitive
24092 case value_t::string: // LCOV_EXCL_LINE
24093 case value_t::boolean: // LCOV_EXCL_LINE
24094 case value_t::number_integer: // LCOV_EXCL_LINE
24095 case value_t::number_unsigned: // LCOV_EXCL_LINE
24096 case value_t::number_float: // LCOV_EXCL_LINE
24097 case value_t::binary: // LCOV_EXCL_LINE
24098 case value_t::discarded: // LCOV_EXCL_LINE
24099 default: // LCOV_EXCL_LINE
24100 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24101 }
24102 };
24103
24104 // wrapper for "remove" operation; remove value at ptr
24105 const auto operation_remove = [this, &result](json_pointer& ptr)
24106 {
24107 // get reference to parent of JSON pointer ptr
24108 const auto last_path = ptr.back();
24109 ptr.pop_back();
24110 basic_json& parent = result.at(ptr);
24111
24112 // remove child
24113 if (parent.is_object())
24114 {
24115 // perform range check
24116 auto it = parent.find(last_path);
24117 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24118 {
24119 parent.erase(it);
24120 }
24121 else
24122 {
24123 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24124 }
24125 }
24126 else if (parent.is_array())
24127 {
24128 // note erase performs range check
24129 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24130 }
24131 };
24132
24133 // type check: top level value must be an array
24134 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24135 {
24136 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24137 }
24138
24139 // iterate and apply the operations
24140 for (const auto& val : json_patch)
24141 {
24142 // wrapper to get a value for an operation
24143 const auto get_value = [&val](const std::string& op,
24144 const std::string& member,
24145 bool string_type) -> basic_json&
24146 {
24147 // find value
24148 auto it = val.m_data.m_value.object->find(member);
24149
24150 // context-sensitive error message
24151 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
24152
24153 // check if desired value is present
24154 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24155 {
24156 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24157 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24158 }
24159
24160 // check if result is of type string
24161 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24162 {
24163 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24164 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24165 }
24166
24167 // no error: return value
24168 return it->second;
24169 };
24170
24171 // type check: every element of the array must be an object
24172 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24173 {
24174 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24175 }
24176
24177 // collect mandatory members
24178 const auto op = get_value("op", "op", true).template get<std::string>();
24179 const auto path = get_value(op, "path", true).template get<std::string>();
24180 json_pointer ptr(path);
24181
24182 switch (get_op(op))
24183 {
24184 case patch_operations::add:
24185 {
24186 operation_add(ptr, get_value("add", "value", false));
24187 break;
24188 }
24189
24190 case patch_operations::remove:
24191 {
24192 operation_remove(ptr);
24193 break;
24194 }
24195
24196 case patch_operations::replace:
24197 {
24198 // the "path" location must exist - use at()
24199 result.at(ptr) = get_value("replace", "value", false);
24200 break;
24201 }
24202
24203 case patch_operations::move:
24204 {
24205 const auto from_path = get_value("move", "from", true).template get<std::string>();
24206 json_pointer from_ptr(from_path);
24207
24208 // the "from" location must exist - use at()
24209 basic_json const v = result.at(from_ptr);
24210
24211 // The move operation is functionally identical to a
24212 // "remove" operation on the "from" location, followed
24213 // immediately by an "add" operation at the target
24214 // location with the value that was just removed.
24215 operation_remove(from_ptr);
24216 operation_add(ptr, v);
24217 break;
24218 }
24219
24220 case patch_operations::copy:
24221 {
24222 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24223 const json_pointer from_ptr(from_path);
24224
24225 // the "from" location must exist - use at()
24226 basic_json const v = result.at(from_ptr);
24227
24228 // The copy is functionally identical to an "add"
24229 // operation at the target location using the value
24230 // specified in the "from" member.
24231 operation_add(ptr, v);
24232 break;
24233 }
24234
24235 case patch_operations::test:
24236 {
24237 bool success = false;
24238 JSON_TRY
24239 {
24240 // check if "value" matches the one at "path"
24241 // the "path" location must exist - use at()
24242 success = (result.at(ptr) == get_value("test", "value", false));
24243 }
24245 {
24246 // ignore out of range errors: success remains false
24247 }
24248
24249 // throw an exception if test fails
24250 if (JSON_HEDLEY_UNLIKELY(!success))
24251 {
24252 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24253 }
24254
24255 break;
24256 }
24257
24258 case patch_operations::invalid:
24259 default:
24260 {
24261 // op must be "add", "remove", "replace", "move", "copy", or
24262 // "test"
24263 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24264 }
24265 }
24266 }
24267 }
24268
24271 basic_json patch(const basic_json& json_patch) const
24272 {
24273 basic_json result = *this;
24274 result.patch_inplace(json_patch);
24275 return result;
24276 }
24277
24281 static basic_json diff(const basic_json& source, const basic_json& target,
24282 const std::string& path = "")
24283 {
24284 // the patch
24285 basic_json result(value_t::array);
24286
24287 // if the values are the same, return empty patch
24288 if (source == target)
24289 {
24290 return result;
24291 }
24292
24293 if (source.type() != target.type())
24294 {
24295 // different types: replace value
24296 result.push_back(
24297 {
24298 {"op", "replace"}, {"path", path}, {"value", target}
24299 });
24300 return result;
24301 }
24302
24303 switch (source.type())
24304 {
24305 case value_t::array:
24306 {
24307 // first pass: traverse common elements
24308 std::size_t i = 0;
24309 while (i < source.size() && i < target.size())
24310 {
24311 // recursive call to compare array values at index i
24312 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24313 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24314 ++i;
24315 }
24316
24317 // We now reached the end of at least one array
24318 // in a second pass, traverse the remaining elements
24319
24320 // remove my remaining elements
24321 const auto end_index = static_cast<difference_type>(result.size());
24322 while (i < source.size())
24323 {
24324 // add operations in reverse order to avoid invalid
24325 // indices
24326 result.insert(result.begin() + end_index, object(
24327 {
24328 {"op", "remove"},
24329 {"path", detail::concat(path, '/', std::to_string(i))}
24330 }));
24331 ++i;
24332 }
24333
24334 // add other remaining elements
24335 while (i < target.size())
24336 {
24337 result.push_back(
24338 {
24339 {"op", "add"},
24340 {"path", detail::concat(path, "/-")},
24341 {"value", target[i]}
24342 });
24343 ++i;
24344 }
24345
24346 break;
24347 }
24348
24349 case value_t::object:
24350 {
24351 // first pass: traverse this object's elements
24352 for (auto it = source.cbegin(); it != source.cend(); ++it)
24353 {
24354 // escape the key name to be used in a JSON patch
24355 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24356
24357 if (target.find(it.key()) != target.end())
24358 {
24359 // recursive call to compare object values at key it
24360 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24361 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24362 }
24363 else
24364 {
24365 // found a key that is not in o -> remove it
24366 result.push_back(object(
24367 {
24368 {"op", "remove"}, {"path", path_key}
24369 }));
24370 }
24371 }
24372
24373 // second pass: traverse other object's elements
24374 for (auto it = target.cbegin(); it != target.cend(); ++it)
24375 {
24376 if (source.find(it.key()) == source.end())
24377 {
24378 // found a key that is not in this -> add it
24379 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24380 result.push_back(
24381 {
24382 {"op", "add"}, {"path", path_key},
24383 {"value", it.value()}
24384 });
24385 }
24386 }
24387
24388 break;
24389 }
24390
24391 case value_t::null:
24392 case value_t::string:
24393 case value_t::boolean:
24394 case value_t::number_integer:
24395 case value_t::number_unsigned:
24396 case value_t::number_float:
24397 case value_t::binary:
24398 case value_t::discarded:
24399 default:
24400 {
24401 // both primitive type: replace value
24402 result.push_back(
24403 {
24404 {"op", "replace"}, {"path", path}, {"value", target}
24405 });
24406 break;
24407 }
24408 }
24409
24410 return result;
24411 }
24413
24415 // JSON Merge Patch functions //
24417
24420
24423 void merge_patch(const basic_json& apply_patch)
24424 {
24425 if (apply_patch.is_object())
24426 {
24427 if (!is_object())
24428 {
24429 *this = object();
24430 }
24431 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24432 {
24433 if (it.value().is_null())
24434 {
24435 erase(it.key());
24436 }
24437 else
24438 {
24439 operator[](it.key()).merge_patch(it.value());
24440 }
24441 }
24442 }
24443 else
24444 {
24445 *this = apply_patch;
24446 }
24447 }
24448
24450};
24451
24456{
24457 return j.dump();
24458}
24459
24460inline namespace literals
24461{
24462 inline namespace json_literals
24463 {
24464
24468#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24469 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24470#else
24471 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24472#endif
24473 {
24474 return nlohmann::json::parse(s, s + n);
24475 }
24476
24480#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24481 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24482#else
24483 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24484#endif
24485 {
24486 return nlohmann::json::json_pointer(std::string(s, n));
24487 }
24488
24489 } // namespace json_literals
24490} // namespace literals
24492
24494// nonmember support //
24496
24497namespace std // NOLINT(cert-dcl58-cpp)
24498{
24499
24503 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24504 {
24505 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24506 {
24507 return nlohmann::detail::hash(j);
24508 }
24509 };
24510
24511 // specialization for std::less<value_t>
24512 template<>
24513 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24514 {
24519 bool operator()(::nlohmann::detail::value_t lhs,
24520 ::nlohmann::detail::value_t rhs) const noexcept
24521 {
24522#if JSON_HAS_THREE_WAY_COMPARISON
24523 return std::is_lt(lhs <=> rhs); // *NOPAD*
24524#else
24525 return ::nlohmann::detail::operator<(lhs, rhs);
24526#endif
24527 }
24528 };
24529
24530 // C++20 prohibit function specialization in the std namespace.
24531#ifndef JSON_HAS_CPP_20
24532
24536 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24537 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24538 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24539 {
24540 j1.swap(j2);
24541 }
24542
24543#endif
24544
24545} // namespace std
24546
24547#if JSON_USE_GLOBAL_UDLS
24548#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24549using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24550using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24551#else
24552using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24553using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24554#endif
24555#endif
24556
24557// #include <nlohmann/detail/macro_unscope.hpp>
24558// __ _____ _____ _____
24559// __| | __| | | | JSON for Modern C++
24560// | | |__ | | | | | | version 3.11.3
24561// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24562//
24563// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24564// SPDX-License-Identifier: MIT
24565
24566
24567
24568// restore clang diagnostic settings
24569#if defined(__clang__)
24570#pragma clang diagnostic pop
24571#endif
24572
24573// clean up
24574#undef JSON_ASSERT
24575#undef JSON_INTERNAL_CATCH
24576#undef JSON_THROW
24577#undef JSON_PRIVATE_UNLESS_TESTED
24578#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24579#undef NLOHMANN_BASIC_JSON_TPL
24580#undef JSON_EXPLICIT
24581#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24582#undef JSON_INLINE_VARIABLE
24583#undef JSON_NO_UNIQUE_ADDRESS
24584#undef JSON_DISABLE_ENUM_SERIALIZATION
24585#undef JSON_USE_GLOBAL_UDLS
24586
24587#ifndef JSON_TEST_KEEP_MACROS
24588#undef JSON_CATCH
24589#undef JSON_TRY
24590#undef JSON_HAS_CPP_11
24591#undef JSON_HAS_CPP_14
24592#undef JSON_HAS_CPP_17
24593#undef JSON_HAS_CPP_20
24594#undef JSON_HAS_FILESYSTEM
24595#undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24596#undef JSON_HAS_THREE_WAY_COMPARISON
24597#undef JSON_HAS_RANGES
24598#undef JSON_HAS_STATIC_RTTI
24599#undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24600#endif
24601
24602// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24603// __ _____ _____ _____
24604// __| | __| | | | JSON for Modern C++
24605// | | |__ | | | | | | version 3.11.3
24606// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24607//
24608// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24609// SPDX-License-Identifier: MIT
24610
24611
24612
24613#undef JSON_HEDLEY_ALWAYS_INLINE
24614#undef JSON_HEDLEY_ARM_VERSION
24615#undef JSON_HEDLEY_ARM_VERSION_CHECK
24616#undef JSON_HEDLEY_ARRAY_PARAM
24617#undef JSON_HEDLEY_ASSUME
24618#undef JSON_HEDLEY_BEGIN_C_DECLS
24619#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24620#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24621#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24622#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24623#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24624#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24625#undef JSON_HEDLEY_CLANG_HAS_WARNING
24626#undef JSON_HEDLEY_COMPCERT_VERSION
24627#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24628#undef JSON_HEDLEY_CONCAT
24629#undef JSON_HEDLEY_CONCAT3
24630#undef JSON_HEDLEY_CONCAT3_EX
24631#undef JSON_HEDLEY_CONCAT_EX
24632#undef JSON_HEDLEY_CONST
24633#undef JSON_HEDLEY_CONSTEXPR
24634#undef JSON_HEDLEY_CONST_CAST
24635#undef JSON_HEDLEY_CPP_CAST
24636#undef JSON_HEDLEY_CRAY_VERSION
24637#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24638#undef JSON_HEDLEY_C_DECL
24639#undef JSON_HEDLEY_DEPRECATED
24640#undef JSON_HEDLEY_DEPRECATED_FOR
24641#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24642#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24643#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24644#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24645#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24646#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24647#undef JSON_HEDLEY_DIAGNOSTIC_POP
24648#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24649#undef JSON_HEDLEY_DMC_VERSION
24650#undef JSON_HEDLEY_DMC_VERSION_CHECK
24651#undef JSON_HEDLEY_EMPTY_BASES
24652#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24653#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24654#undef JSON_HEDLEY_END_C_DECLS
24655#undef JSON_HEDLEY_FLAGS
24656#undef JSON_HEDLEY_FLAGS_CAST
24657#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24658#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24659#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24660#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24661#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24662#undef JSON_HEDLEY_GCC_HAS_FEATURE
24663#undef JSON_HEDLEY_GCC_HAS_WARNING
24664#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24665#undef JSON_HEDLEY_GCC_VERSION
24666#undef JSON_HEDLEY_GCC_VERSION_CHECK
24667#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24668#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24669#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24670#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24671#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24672#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24673#undef JSON_HEDLEY_GNUC_HAS_WARNING
24674#undef JSON_HEDLEY_GNUC_VERSION
24675#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24676#undef JSON_HEDLEY_HAS_ATTRIBUTE
24677#undef JSON_HEDLEY_HAS_BUILTIN
24678#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24679#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24680#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24681#undef JSON_HEDLEY_HAS_EXTENSION
24682#undef JSON_HEDLEY_HAS_FEATURE
24683#undef JSON_HEDLEY_HAS_WARNING
24684#undef JSON_HEDLEY_IAR_VERSION
24685#undef JSON_HEDLEY_IAR_VERSION_CHECK
24686#undef JSON_HEDLEY_IBM_VERSION
24687#undef JSON_HEDLEY_IBM_VERSION_CHECK
24688#undef JSON_HEDLEY_IMPORT
24689#undef JSON_HEDLEY_INLINE
24690#undef JSON_HEDLEY_INTEL_CL_VERSION
24691#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24692#undef JSON_HEDLEY_INTEL_VERSION
24693#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24694#undef JSON_HEDLEY_IS_CONSTANT
24695#undef JSON_HEDLEY_IS_CONSTEXPR_
24696#undef JSON_HEDLEY_LIKELY
24697#undef JSON_HEDLEY_MALLOC
24698#undef JSON_HEDLEY_MCST_LCC_VERSION
24699#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24700#undef JSON_HEDLEY_MESSAGE
24701#undef JSON_HEDLEY_MSVC_VERSION
24702#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24703#undef JSON_HEDLEY_NEVER_INLINE
24704#undef JSON_HEDLEY_NON_NULL
24705#undef JSON_HEDLEY_NO_ESCAPE
24706#undef JSON_HEDLEY_NO_RETURN
24707#undef JSON_HEDLEY_NO_THROW
24708#undef JSON_HEDLEY_NULL
24709#undef JSON_HEDLEY_PELLES_VERSION
24710#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24711#undef JSON_HEDLEY_PGI_VERSION
24712#undef JSON_HEDLEY_PGI_VERSION_CHECK
24713#undef JSON_HEDLEY_PREDICT
24714#undef JSON_HEDLEY_PRINTF_FORMAT
24715#undef JSON_HEDLEY_PRIVATE
24716#undef JSON_HEDLEY_PUBLIC
24717#undef JSON_HEDLEY_PURE
24718#undef JSON_HEDLEY_REINTERPRET_CAST
24719#undef JSON_HEDLEY_REQUIRE
24720#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24721#undef JSON_HEDLEY_REQUIRE_MSG
24722#undef JSON_HEDLEY_RESTRICT
24723#undef JSON_HEDLEY_RETURNS_NON_NULL
24724#undef JSON_HEDLEY_SENTINEL
24725#undef JSON_HEDLEY_STATIC_ASSERT
24726#undef JSON_HEDLEY_STATIC_CAST
24727#undef JSON_HEDLEY_STRINGIFY
24728#undef JSON_HEDLEY_STRINGIFY_EX
24729#undef JSON_HEDLEY_SUNPRO_VERSION
24730#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24731#undef JSON_HEDLEY_TINYC_VERSION
24732#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24733#undef JSON_HEDLEY_TI_ARMCL_VERSION
24734#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24735#undef JSON_HEDLEY_TI_CL2000_VERSION
24736#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24737#undef JSON_HEDLEY_TI_CL430_VERSION
24738#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24739#undef JSON_HEDLEY_TI_CL6X_VERSION
24740#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24741#undef JSON_HEDLEY_TI_CL7X_VERSION
24742#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24743#undef JSON_HEDLEY_TI_CLPRU_VERSION
24744#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24745#undef JSON_HEDLEY_TI_VERSION
24746#undef JSON_HEDLEY_TI_VERSION_CHECK
24747#undef JSON_HEDLEY_UNAVAILABLE
24748#undef JSON_HEDLEY_UNLIKELY
24749#undef JSON_HEDLEY_UNPREDICTABLE
24750#undef JSON_HEDLEY_UNREACHABLE
24751#undef JSON_HEDLEY_UNREACHABLE_RETURN
24752#undef JSON_HEDLEY_VERSION
24753#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24754#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24755#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24756#undef JSON_HEDLEY_VERSION_ENCODE
24757#undef JSON_HEDLEY_WARNING
24758#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24759#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24760#undef JSON_HEDLEY_FALL_THROUGH
24761
24762
24763
24764#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:19400
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:20672
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:21905
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:21473
size_type size() const noexcept
returns the number of elements
Definition json.hpp:22246
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:23679
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23611
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.hpp:21045
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22103
reference back()
access the last element
Definition json.hpp:21709
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:20136
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22119
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:24271
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:23459
const_reference front() const
access the first element
Definition json.hpp:21702
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:20665
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22763
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21653
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22022
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:19531
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23630
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:20637
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:19535
data(size_type cnt, const basic_json &val)
Definition json.hpp:23503
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:23874
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition json.hpp:23622
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:23919
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:19526
std::size_t size_type
a type to represent container sizes
Definition json.hpp:19518
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:20609
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:21497
void swap(binary_t &other)
exchanges the values
Definition json.hpp:22840
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:21135
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:22285
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22709
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21146
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:20686
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:22501
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:22389
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:21442
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22191
const_reference back() const
access the last element
Definition json.hpp:21718
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:21800
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:22446
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22780
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:23775
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:20273
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:22613
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:23859
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:19541
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:19666
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:21305
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:22094
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:20644
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22716
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:23638
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22126
data m_data
Definition json.hpp:23521
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:22485
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:20103
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:20314
ValueType & get_to(ValueType &v) const
Definition json.hpp:21112
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23577
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:22069
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:21552
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22110
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:23829
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:23961
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:20284
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20124
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:23663
basic_json flatten() const
return flattened JSON value
Definition json.hpp:23975
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:23790
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:21916
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:19642
const binary_t & get_binary() const
get a binary value
Definition json.hpp:21217
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:22633
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24000
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21605
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition json.hpp:24281
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition json.hpp:19634
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:23933
value_type & reference
the type of an element reference
Definition json.hpp:19511
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:19475
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22039
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:23547
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:23654
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:21952
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:20262
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:21343
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:19549
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:20321
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:21966
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:23538
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:21730
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:22586
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:19662
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21527
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:19521
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:19524
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:20573
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:24423
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:21099
reference operator[](T *key)
Definition json.hpp:21458
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:21239
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:21982
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:20651
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22133
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23584
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:23947
BooleanType boolean_t
a type for a boolean
Definition json.hpp:19650
detail::value_t value_t
Definition json.hpp:19465
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition json.hpp:19629
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22477
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:22085
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:21420
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:20857
~basic_json() noexcept
destructor
Definition json.hpp:20555
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:22154
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:20203
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:22856
binary_t & get_binary()
get a binary value
Definition json.hpp:21205
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22078
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:20630
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:22684
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:23721
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21086
const_reference operator[](T *key) const
Definition json.hpp:21464
data(const value_t v)
Definition json.hpp:23498
reference operator[](size_type idx)
access specified array element
Definition json.hpp:21361
basic_json(const JsonRef &ref)
Definition json.hpp:20442
JSONSerializer< T, SFINAE > json_serializer
Definition json.hpp:19469
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:20532
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23603
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21123
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:19654
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:20846
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:21323
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:20679
void swap(object_t &other)
exchanges the values
Definition json.hpp:22808
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:23984
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:22664
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:20295
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22184
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:22207
void swap(array_t &other)
exchanges the values
Definition json.hpp:22792
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:21923
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:22414
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22046
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:20595
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:22510
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21628
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:20306
data() noexcept=default
StringType string_t
a type for a string
Definition json.hpp:19646
friend class ::nlohmann::detail::parser
Definition json.hpp:19410
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:22422
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21578
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:21285
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:23844
json_value m_value
the value of the current element
Definition json.hpp:23496
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:22147
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:20623
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22012
reference front()
access the first element
Definition json.hpp:21695
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:20602
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:20616
void clear() noexcept
clears the contents
Definition json.hpp:22328
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:23595
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:20515
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:19529
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20116
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:21407
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:19516
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:22606
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22140
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:19658
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:23444
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23561
void swap(string_t &other)
exchanges the values
Definition json.hpp:22824
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20150
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:19533
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:21262
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:19670
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:20446
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22454
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:22535
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:23554
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:20658
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23570
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:23736
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:22567
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:20333
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22030
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:23647
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:21998
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:19467
an internal type for a backed binary type
Definition json.hpp:5892
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:5932
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:5898
std::uint64_t subtype_type
Definition json.hpp:5895
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:5926
BinaryType container_type
Definition json.hpp:5894
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5920
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5908
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:5947
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:5913
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:5954
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:5903
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:5939
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:5961
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9212
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9228
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:9249
binary_reader & operator=(binary_reader &&)=default
serialization to CBOR and MessagePack values
Definition json.hpp:15078
void write_bson(const BasicJsonType &j)
Definition json.hpp:15098
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:16833
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:16840
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15089
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:16862
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false)
Definition json.hpp:15777
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:15451
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15127
general exception of the basic_json class
Definition json.hpp:4373
const int id
the id of the exception
Definition json.hpp:4382
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4393
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4388
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4376
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4399
Definition json.hpp:6189
char char_type
Definition json.hpp:6191
file_input_adapter(const file_input_adapter &)=delete
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6207
file_input_adapter(file_input_adapter &&) noexcept=default
Definition json.hpp:6227
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:6250
~input_stream_adapter()
Definition json.hpp:6231
std::char_traits< char >::int_type get_character()
Definition json.hpp:6260
char char_type
Definition json.hpp:6229
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:6241
exception indicating errors with iterators
Definition json.hpp:4524
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4527
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:12915
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:13489
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13052
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:13434
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13042
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:13381
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:13416
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:13480
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:13295
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:13589
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition json.hpp:12947
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:13336
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13233
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:13443
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13551
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:12945
pointer operator->() const
dereference the iterator
Definition json.hpp:13191
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:13614
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:13522
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition json.hpp:12951
iter_impl(iter_impl &&) noexcept=default
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:12940
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:13500
reference value() const
return the value of an iterator
Definition json.hpp:13605
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:13425
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13244
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:12943
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13147
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13511
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13027
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:13372
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:13284
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13017
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13108
Definition json.hpp:12895
iteration_proxy_value operator++(int) &
Definition json.hpp:5243
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5252
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5258
std::ptrdiff_t difference_type
Definition json.hpp:5189
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5210
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5235
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5194
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5300
const string_type & key() const
return key of the iterator
Definition json.hpp:5264
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
std::input_iterator_tag iterator_category
Definition json.hpp:5193
proxy class for the items() function
Definition json.hpp:12894
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5333
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5317
iteration_proxy & operator=(iteration_proxy const &)=default
Definition json.hpp:6282
char_traits< char_type >::int_type get_character()
Definition json.hpp:6290
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6286
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:6284
Definition json.hpp:14819
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:14827
json_ref(value_type &&value)
Definition json.hpp:14823
value_type const & operator*() const
Definition json.hpp:14858
value_type const * operator->() const
Definition json.hpp:14863
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:14831
json_ref(Args &&... args)
Definition json.hpp:14838
value_type moved_or_copied() const
Definition json.hpp:14849
BasicJsonType value_type
Definition json.hpp:14821
a template for a reverse iterator class
Definition json.hpp:13668
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:13684
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:13696
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:13690
std::ptrdiff_t difference_type
Definition json.hpp:13670
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:13708
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13732
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:13738
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:13726
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:13674
reference value() const
return the value of an iterator
Definition json.hpp:13745
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:13681
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:13702
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:13672
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13720
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:13677
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:13714
Definition json.hpp:7291
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:7294
bool end_object()
Definition json.hpp:7344
bool start_object(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:7334
bool binary(binary_t &)
Definition json.hpp:7329
bool number_integer(number_integer_t)
Definition json.hpp:7309
bool start_array(std::size_t=static_cast< std::size_t >(-1))
Definition json.hpp:7349
bool boolean(bool)
Definition json.hpp:7304
bool null()
Definition json.hpp:7299
bool end_array()
Definition json.hpp:7354
bool number_unsigned(number_unsigned_t)
Definition json.hpp:7314
bool string(string_t &)
Definition json.hpp:7324
typename BasicJsonType::binary_t binary_t
Definition json.hpp:7297
bool number_float(number_float_t, const string_t &)
Definition json.hpp:7319
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:7359
bool key(string_t &)
Definition json.hpp:7339
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:7293
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:7295
typename BasicJsonType::string_t string_t
Definition json.hpp:7296
Definition json.hpp:6984
bool boolean(bool val)
Definition json.hpp:7015
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:7172
typename BasicJsonType::string_t string_t
Definition json.hpp:6989
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:7033
constexpr bool is_errored() const
Definition json.hpp:7184
bool string(string_t &val)
Definition json.hpp:7039
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6987
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6990
bool start_object(std::size_t len)
Definition json.hpp:7051
bool start_array(std::size_t len)
Definition json.hpp:7122
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6986
bool end_array()
Definition json.hpp:7139
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
bool key(string_t &val)
Definition json.hpp:7069
bool end_object()
Definition json.hpp:7086
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:6992
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:6991
bool null()
Definition json.hpp:7009
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:7027
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
json_sax_dom_callback_parser(BasicJsonType &r, const parser_callback_t cb, const bool allow_exceptions_=true)
Definition json.hpp:6994
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6988
bool number_integer(number_integer_t val)
Definition json.hpp:7021
bool binary(binary_t &val)
Definition json.hpp:7045
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:6801
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool string(string_t &val)
Definition json.hpp:6855
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:6814
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:6922
bool null()
Definition json.hpp:6825
typename BasicJsonType::string_t string_t
Definition json.hpp:6806
bool start_object(std::size_t len)
Definition json.hpp:6867
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6804
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:6843
bool number_integer(number_integer_t val)
Definition json.hpp:6837
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6803
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:6861
json_sax_dom_parser(json_sax_dom_parser &&)=default
bool boolean(bool val)
Definition json.hpp:6831
bool end_array()
Definition json.hpp:6911
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:6849
bool end_object()
Definition json.hpp:6889
constexpr bool is_errored() const
Definition json.hpp:6934
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6807
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6805
bool start_array(std::size_t len)
Definition json.hpp:6899
bool key(string_t &val)
Definition json.hpp:6879
Definition json.hpp:7408
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7435
token_type
token types for the parser
Definition json.hpp:7412
lexical analysis
Definition json.hpp:7485
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8859
void skip_whitespace()
Definition json.hpp:8873
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7496
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8846
std::string get_token_string() const
Definition json.hpp:8821
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8785
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8813
token_type scan()
Definition json.hpp:8881
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8791
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7494
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8803
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8797
exception indicating other library errors
Definition json.hpp:4576
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4579
exception indicating access out of the defined range
Definition json.hpp:4559
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4562
Definition json.hpp:15036
output_adapter(StringType &s)
Definition json.hpp:15047
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:15043
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:15039
output adapter for output streams
Definition json.hpp:14988
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:14990
void write_character(CharType c) override
Definition json.hpp:14994
output adapter for basic_string
Definition json.hpp:15013
void write_character(CharType c) override
Definition json.hpp:15019
output_string_adapter(StringType &s) noexcept
Definition json.hpp:15015
output adapter for byte vectors
Definition json.hpp:14963
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:14965
void write_character(CharType c) override
Definition json.hpp:14969
exception indicating a parse error
Definition json.hpp:4471
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4483
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4491
const std::size_t byte
byte index of the parse error
Definition json.hpp:4508
syntax analysis
Definition json.hpp:12228
parser(InputAdapterType &&adapter, const parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition json.hpp:12238
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:12260
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:12320
bool sax_parse(SAX *sax, const bool strict=true)
Definition json.hpp:12328
Definition json.hpp:12732
primitive_iterator_t & operator++() noexcept
Definition json.hpp:12794
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:12826
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:12761
primitive_iterator_t & operator--() noexcept
Definition json.hpp:12807
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:12755
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:12777
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:12767
primitive_iterator_t operator++(int) &noexcept
Definition json.hpp:12800
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:12820
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:12772
constexpr difference_type get_value() const noexcept
Definition json.hpp:12743
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:12789
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:12782
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:12749
primitive_iterator_t operator--(int) &noexcept
Definition json.hpp:12813
Definition json.hpp:18059
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:18983
std::uint8_t state
Definition json.hpp:18401
std::size_t bytes_after_last_accept
Definition json.hpp:18405
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18074
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:18399
std::size_t undumped_chars
Definition json.hpp:18406
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:18978
const char decimal_point
the locale's decimal point character
Definition json.hpp:18980
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:18991
string_t indent_string
the indentation string
Definition json.hpp:18988
const std::lconv * loc
the locale
Definition json.hpp:18976
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:18973
const char indent_char
the indentation character
Definition json.hpp:18986
std::size_t bytes
Definition json.hpp:18402
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:18114
serializer(const serializer &)=delete
serializer(serializer &&)=delete
Definition json.hpp:6606
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:6614
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6621
contiguous_bytes_input_adapter && get()
Definition json.hpp:6624
exception indicating executing a member function with a wrong type
Definition json.hpp:4542
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4545
Definition json.hpp:6441
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6448
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:6445
char char_type
Definition json.hpp:6443
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:13840
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:13935
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:13862
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:13942
friend bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for equality
Definition json.hpp:14735
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:13866
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14001
void pop_back()
remove last reference token
Definition json.hpp:13963
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:13872
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:13920
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:13994
friend bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointer for less-than
Definition json.hpp:14785
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:13902
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:13927
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:13949
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:13912
friend class json_pointer
Definition json.hpp:13846
const string_t & back() const
return last reference token
Definition json.hpp:13975
friend bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
compares two JSON pointers for inequality
Definition json.hpp:14760
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:13893
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:13987
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5379
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2596
#define JSON_HEDLEY_CONST
Definition json.hpp:1818
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1102
#define JSON_INLINE_VARIABLE
Definition json.hpp:2499
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1448
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2559
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1713
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14735
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1606
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2526
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:24455
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2047
#define JSON_CATCH(exception)
Definition json.hpp:2525
#define JSON_ASSERT(x)
Definition json.hpp:2552
#define JSON_THROW(exception)
Definition json.hpp:2523
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:77
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14785
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2606
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1714
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12118
#define JSON_TRY
Definition json.hpp:2524
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:144
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2505
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2786
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:14760
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:134
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12115
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1103
#define JSON_EXPLICIT
Definition json.hpp:2823
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1396
#define JSON_HEDLEY_PURE
Definition json.hpp:1787
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:22881
root
Definition addOrder.py:80
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:17398
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:17234
Target reinterpret_bits(const Source source)
Definition json.hpp:16954
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17095
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.hpp:17452
constexpr int kAlpha
Definition json.hpp:17217
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:17734
constexpr int kGamma
Definition json.hpp:17218
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:17493
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:17834
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:17886
constexpr bool is_transparent()
Definition json.hpp:4195
constexpr bool is_c_string()
Definition json.hpp:4167
detail namespace with internal helper functions
Definition json.hpp:249
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3192
input_format_t
the supported input formats
Definition json.hpp:6177
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:300
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:5781
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3518
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:3993
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4291
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:9070
OutStringType concat(Args &&... args)
Definition json.hpp:4350
typename T::value_type value_type_t
Definition json.hpp:3503
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:9050
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:12218
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3223
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:17971
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:309
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4273
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3096
parse_event_t
Definition json.hpp:12202
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:294
typename T::pointer pointer_t
Definition json.hpp:3509
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:5011
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:9038
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:4822
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3184
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:14958
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:306
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:9073
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:9035
T conditional_static_cast(U value)
Definition json.hpp:4051
typename T::difference_type difference_type_t
Definition json.hpp:3506
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:2971
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4285
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5343
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4073
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3597
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4020
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:6579
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9185
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3748
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3200
void concat_into(OutStringType &)
Definition json.hpp:4266
constexpr bool value_in_range_of(T val)
Definition json.hpp:4151
value_t
the JSON type enumeration
Definition json.hpp:2873
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3521
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.hpp:4905
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6023
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:13790
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4270
typename make_void< Ts... >::type void_t
Definition json.hpp:255
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:6005
decltype(std::declval< T & >().parse_error( std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:9080
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:4024
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:2902
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6522
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3745
typename T::iterator_category iterator_category_t
Definition json.hpp:3515
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:9042
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:312
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:9054
error_handler_t
how to treat decoding errors
Definition json.hpp:18051
@ strict
throw a type_error exception in case of invalid UTF-8
@ ignore
ignore invalid UTF-8 sequences
@ replace
replace invalid UTF-8 sequences with U+FFFD
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:4011
std::size_t concat_length()
Definition json.hpp:4235
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4157
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3082
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:9046
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:4665
typename T::key_compare detect_key_compare
Definition json.hpp:3581
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5643
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:4679
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4282
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:9077
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:5005
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4288
typename T::key_type key_type_t
Definition json.hpp:3500
typename T::reference reference_t
Definition json.hpp:3512
typename T::is_transparent detect_is_transparent
Definition json.hpp:3987
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4077
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4279
typename T::mapped_type mapped_type_t
Definition json.hpp:3497
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:9066
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:9062
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:2991
void int_to_string(string_type &target, std::size_t value)
Definition json.hpp:5180
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:9058
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3524
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4276
Definition json.hpp:24461
Definition json.hpp:5364
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:24536
namespace for Niels Lohmann
Definition json.hpp:5834
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:5858
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.hpp:5848
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:5838
Definition json.hpp:3589
typename BasicJsonType::object_t object_t
Definition json.hpp:3590
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3592
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3591
signed char char_type
Definition json.hpp:3636
static constexpr int_type eof() noexcept
Definition json.hpp:3650
uint64_t int_type
Definition json.hpp:3637
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3645
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3640
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3621
static constexpr int_type eof() noexcept
Definition json.hpp:3626
unsigned char char_type
Definition json.hpp:3612
uint64_t int_type
Definition json.hpp:3613
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3616
Definition json.hpp:3606
Definition json.hpp:3661
decltype(input_adapter(begin(std::declval< ContainerType >()), end(std::declval< ContainerType >()))) adapter_type
Definition json.hpp:6545
Definition json.hpp:281
std::false_type value_t
Definition json.hpp:282
Default type
Definition json.hpp:283
Definition json.hpp:17082
diyfp w
Definition json.hpp:17083
diyfp minus
Definition json.hpp:17084
diyfp plus
Definition json.hpp:17085
Definition json.hpp:17221
std::uint64_t f
Definition json.hpp:17222
int e
Definition json.hpp:17223
int k
Definition json.hpp:17224
Definition json.hpp:16964
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:16988
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:17070
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17053
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:16976
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:16970
static constexpr int kPrecision
Definition json.hpp:16965
std::uint64_t f
Definition json.hpp:16967
int e
Definition json.hpp:16968
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5568
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5543
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5533
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5555
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5584
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5472
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5481
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5426
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5494
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5520
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5507
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5603
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5624
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5613
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5448
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5459
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5439
Definition json.hpp:5420
Definition json.hpp:5100
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.hpp:5102
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3543
Definition json.hpp:3528
Definition json.hpp:3584
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3558
Definition json.hpp:3553
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3573
Definition json.hpp:3568
Definition json.hpp:4616
Definition json.hpp:3124
T value_type
Definition json.hpp:3125
static constexpr std::size_t size() noexcept
Definition json.hpp:3126
an iterator value
Definition json.hpp:12848
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:12852
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:12854
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:12850
Definition json.hpp:3477
Definition json.hpp:3464
Definition json.hpp:4182
Definition json.hpp:3978
Definition json.hpp:3861
Definition json.hpp:3932
Definition json.hpp:3782
Definition json.hpp:3819
static constexpr auto value
Definition json.hpp:3820
Definition json.hpp:3935
Definition json.hpp:3948
Definition json.hpp:3755
Definition json.hpp:3905
Definition json.hpp:3815
Definition json.hpp:3826
ConstructibleStringType laundered_type
Definition json.hpp:3831
static constexpr auto value
Definition json.hpp:3834
Definition json.hpp:3951
Definition json.hpp:3693
Definition json.hpp:3674
Definition json.hpp:297
Definition json.hpp:3536
static constexpr bool value
Definition json.hpp:3537
Definition json.hpp:6498
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:6499
Definition json.hpp:3708
Definition json.hpp:3957
Definition json.hpp:3487
Definition json.hpp:4039
char x[2]
Definition json.hpp:4040
Definition json.hpp:4035
static one test(decltype(&C::capacity))
@ value
Definition json.hpp:4046
char one
Definition json.hpp:4036
static two test(...)
Definition json.hpp:3727
static constexpr bool value
Definition json.hpp:3741
Definition json.hpp:9117
Definition json.hpp:9086
static constexpr bool value
Definition json.hpp:9099
Definition json.hpp:3968
Definition json.hpp:4204
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6510
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6514
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:6488
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6487
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6490
IteratorType iterator_type
Definition json.hpp:6486
std::random_access_iterator_tag iterator_category
Definition json.hpp:3304
Definition json.hpp:3292
Definition json.hpp:3273
Default base class of the basic_json class.
Definition json.hpp:13787
Definition json.hpp:252
void type
Definition json.hpp:253
Definition json.hpp:3668
Definition json.hpp:267
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition json.hpp:14944
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
Definition json.hpp:3037
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3041
std::size_t lines_read
the number of lines read
Definition json.hpp:3043
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3039
Definition json.hpp:3207
Definition json.hpp:3213
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3214
Definition json.hpp:5801
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:5803
Definition json.hpp:3144
Definition json.hpp:3163
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3164
static constexpr bool test(T val)
Definition json.hpp:4135
static constexpr bool test(T)
Definition json.hpp:4144
Definition json.hpp:4130
static constexpr bool test(T val)
Definition json.hpp:4089
static constexpr bool test(T val)
Definition json.hpp:4109
static constexpr bool test(T val)
Definition json.hpp:4099
static constexpr bool test(T val)
Definition json.hpp:4119
Definition json.hpp:4084
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6380
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6322
Definition json.hpp:6316
SAX interface.
Definition json.hpp:6671
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:6672
typename BasicJsonType::string_t string_t
Definition json.hpp:6675
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:6674
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:6673
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:6676
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19033
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19036
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:19327
typename Container::value_type value_type
Definition json.hpp:19040
std::equal_to< Key > key_compare
Definition json.hpp:19044
iterator erase(iterator pos)
Definition json.hpp:19205
T mapped_type
Definition json.hpp:19035
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19050
T & operator[](KeyType &&key)
Definition json.hpp:19092
typename Container::iterator iterator
Definition json.hpp:19037
const T & at(KeyType &&key) const
Definition json.hpp:19152
T & at(KeyType &&key)
Definition json.hpp:19124
const T & operator[](KeyType &&key) const
Definition json.hpp:19104
iterator find(const key_type &key)
Definition json.hpp:19289
iterator erase(iterator first, iterator last)
Definition json.hpp:19210
const T & at(const key_type &key) const
Definition json.hpp:19137
const_iterator find(const key_type &key) const
Definition json.hpp:19315
T & operator[](const key_type &key)
Definition json.hpp:19085
size_type erase(KeyType &&key)
Definition json.hpp:19186
typename Container::size_type size_type
Definition json.hpp:19039
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19049
void insert(InputIt first, InputIt last)
Definition json.hpp:19350
size_type count(const key_type &key) const
Definition json.hpp:19263
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:19072
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:19346
size_type erase(const key_type &key)
Definition json.hpp:19165
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19054
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:19332
size_type count(KeyType &&key) const
Definition json.hpp:19277
Key key_type
Definition json.hpp:19034
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19052
const T & operator[](const key_type &key) const
Definition json.hpp:19097
iterator find(KeyType &&key)
Definition json.hpp:19303
T & at(const key_type &key)
Definition json.hpp:19109
typename Container::const_iterator const_iterator
Definition json.hpp:19038
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19057
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:24505
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:24519